CSS'nin ne kadar iş yaptığını hiç düşündünüz mü? Tek bir özelliği değiştirdiğinizde web sitenizin tamamı birden farklı bir düzende görünür. Bu bir tür sihir. Şu ana kadar, web geliştirici topluluğu olarak bu büyüye yalnızca tanık olup gözlemledik. Peki kendi sihretimizi yaratmak istersek? Sihirbaz olmak isterseniz ne olur?
Houdini'ye girin!
Houdini görev gücü, 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şur. Çalışma grubu, gerçek web standartları haline gelmeleri için W3C tarafından kabul edilmelerini sağlamak amacıyla taslak koleksiyonu üzerinde çalışıyor. Kendilerine birkaç üst düzey hedef belirlediler, bunları spesifikasyon taslakları haline getirdiler ve bu taslaklar da destekleyici, alt düzey spesifikasyon taslakları oluşturdu.
"Houdini"den bahsedildiğinde genellikle bu taslakların koleksiyonu kastedilir. Bu makale yazılırken taslak listesi eksikti ve taslakların bazıları yalnızca yer tutucuydu.
Teknik özellikler
İş akışları (spec)
İş akışları tek başlarına kullanışlı değildir. Bunlar sonraki taslakların birçoğunu mümkün hale getirmek için kullanılan bir kavramdır. "İş parçası" ifadesini gördüğünüzde aklınıza Web İşleyiciler geldiyse haklısınız. Bu iki kavram arasında çok fazla örtüşme vardır. Peki, zaten çalışanlarımız varken neden yeni bir şeye ihtiyaç duyuyoruz?
Houdini'nin amacı, web geliştiricilerin kendi kodlarını CSS motoruna ve çevre sistemlere bağlamasına olanak tanıyan yeni API'ler sunmaktır. Bu kod parçalarından bazılarının her tek kare çalıştırılması gerektiğini varsaymak muhtemelen gerçekçi olmayacaktır. Bazıları tanımı gereği Web İşleyici spesifikasyonundan alıntı:
Bu durum, web işçilerinin Houdini'nin yapmayı planladığı şeylere uygun olmadığı anlamına geliyor. Dolayısıyla işcıklar icat edildi. Çalışma öğeleri, imzaları çalışma öğesinin türüne göre önceden tanımlanmış bir yöntem koleksiyonunu tanımlamak için ES2015 sınıflarından yararlanır. Bu cihazlar hafif ve kısa ömürlüdür.
CSS Paint API (özellik)
Paint API, Chrome 65'te varsayılan olarak etkindir. Ayrıntılı girişi okuyun.
Birleştirici iş akışı
Burada açıklanan API kullanımdan kaldırılmıştır. Oluşturucu iş parçası yeniden tasarlandı ve artık "Animasyon İş Parçası" olarak öneriliyor. API'nin mevcut yinelemesi hakkında daha fazla bilgi edinin.
Oluşturucu iş parçası spesifikasyonu WICG'ye taşınmış ve üzerinde çalışılacak olsa da beni en çok heyecanlandıran spesifikasyon bu. Bazı işlemler CSS motoru tarafından bilgisayarınızın grafik kartına aktarılır. Bu durum hem grafik kartınıza hem de genel olarak 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 üzerine boyar (gelecekte bir boyama iş parçası kullanılarak). Son adımda, artık boyanmış olan bu tek tek katmanların tümü, ekranınızda görünen nihai görüntüyü oluşturmak için z-dizinlerine, 3D dönüşümlere ve benzeri öğelere göre üst üste yığılır ve birbirinin üzerine yerleştirilir. Bu işleme kompozisyon adı verilir ve kompozitör tarafından yürütülür.
Birleştirme işleminin avantajı, sayfa biraz kaydırılırken tüm öğelerin kendilerini yeniden boyaması gerekmemesidir. Bunun yerine, önceki karedeki katmanları yeniden kullanabilir ve güncellenmiş kaydırma konumuyla birlikte birleştiriciyi yeniden çalıştırabilirsiniz. Bu sayede işler hızlıca halledilir. Bu sayede 60 fps'ye ulaşabiliriz.
Adından da anlaşılacağı gibi, karıştırıcı iş parçası, karıştırıcıya bağlanmanıza ve bir öğenin önceden boyanmış katmanının diğer katmanların üzerine yerleştirilme ve katmanlandırılma şeklini etkilemenize olanak tanır.
Daha ayrıntılı olarak belirtmek gerekirse tarayıcıya belirli bir DOM düğümü için oluşturma işlemine katılmak istediğinizi söyleyebilir ve kaydırma konumu, transform
veya opacity
gibi belirli özelliklere erişim isteğinde bulunabilirsiniz. Bu, öğenin kendi katmanına yerleştirilmesini zorunlu kılar ve her karede kodunuz çağrılır. Katman dönüştürme özelliğini kullanarak katmanınızı hareket ettirebilir ve özelliklerini (opacity
gibi) değiştirebilirsiniz. Böylece 60 fps'de harika şeyler yapabilirsiniz.
Birleştirici iş parçacığı kullanılarak paralaks kaydırma için tam bir uygulama örneğini aşağıda bulabilirsiniz.
// 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, birleştirici işlet için bir çoklu dolgu yazdı. Bu özelliği deneyebilmeniz için açık bir şekilde çok daha yüksek performans etkisine sahip.
Düzen iş akışı (spec)
İlk gerçek özellik taslağı önerildi. Bu özelliğin kullanıma sunulması biraz zaman alacak.
Bu konudaki spesifikasyon da neredeyse boştur ancak konsept ilgi çekicidir: Kendi düzeninizi yazın. Düzenleme iş parçası, display: layout('myLayout')
yapmanıza ve bir düğümün çocuklarını düğümün kutusunda düzenlemek için JavaScript'inizi çalıştırmanıza olanak tanır.
Elbette, CSS'nin flex-box
düzeninin tam JavaScript uygulamasını çalıştırmak, eşdeğer bir doğal uygulamayı çalıştırmaktan daha yavaştır. Ancak, köşeleri kesmenin performans kazancı sağlayabileceği bir senaryo hayal etmek kolaydır. Windows 10 veya duvar tarzı bir düzen gibi karolardan başka bir şey içermeyen bir web sitesi düşünün. Mutlak ve sabit konumlandırma, z-index
kullanılmaz, öğeler hiçbir zaman örtüşmez veya herhangi bir kenarlık ya da taşma olmaz. 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ılı CSSOM (spec)
Yazılı CSSOM (CSS Nesne Modeli veya Basamaklı Stil Sayfaları Nesne Modeli), muhtemelen hepimizin karşılaştığı ve kabul etmeyi öğrendiği bir sorunu ele alıyor. Bir JavaScript satırıyla örnekleyeyim:
$('#someDiv').style.height = getRandomInt() + 'px';
Bir birim eklemek için bir sayıyı bir dizeye dönüştürerek matematik yapıyoruz. Ardından, tarayıcının bu dizeyi ayrıştırmasını ve CSS motoru için tekrar sayıya dönüştürmesini sağlıyoruz. JavaScript ile dönüşümleri değiştirdiğinizde bu durum daha da kötüye gider. Artık yok. CSS'de yazma işlemi başlayacak.
Bu taslak, daha gelişmiş taslaklardan biridir ve üzerinde bir polyfill üzerinde çalışılmaktadır. (Sorumluluk reddi beyanı: polyfill kullanmak, hesaplama yükü açısından daha da fazla artışa neden olur. Amaç, API'nin ne kadar kullanışlı olduğunu göstermektir.)
Dize yerine, her CSS özelliğinin kendi anahtarına ve karşılık gelen değer türüne sahip olduğu bir öğenin StylePropertyMap
üzerinde çalışırsınız. width
gibi özelliklerin değer türü LengthValue
'tür. LengthValue
; em
, rem
, px
, percent
vb. gibi tüm CSS birimlerinin sözlüğüdür. height: calc(5px + 5%)
ayarlandığında LengthValue{px: 5, percent: 5}
elde edilir. 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 özelliklerini (veya resmi olmayan takma adları olan "CSS değişkenleri"ni) biliyor musunuz? Bunlar onlardır ama türleri de vardır. Şimdiye kadar değişkenler yalnızca dize değerlerine sahip olabiliyordu ve basit bir arama ve değiştirme yaklaşımı kullanılıyordu. Bu taslak, değişkenleriniz için bir tür belirtmenizin yanı sıra varsayılan bir değer tanımlamanıza ve bir JavaScript API kullanarak devralma davranışını etkilemenize de olanak tanır. Teknik olarak bu, özel özelliklerin standart CSS geçişleriyle ve animasyonlarla canlandırılmasına da olanak tanır. Bu da dikkate alınması gereken bir durumdur.
["--scale-x", "--scale-y"].forEach(function(name) {
document.registerProperty({
name: name,
syntax: "<number>",
inherits: false,
initialValue: "1"
});
});
Yazı tipi metrikleri
Yazı tipi metrikleri, adından da anlaşılacağı gibidir. X dizesini Y yazı tipi Z boyutunda oluşturduğumda X dizesini 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 özellik çok fazla istendi ve Houdini nihayet bu istekleri yerine getirecek.
Bir saniye, hepsi bu kadar da değil!
Houdini'nin taslak listesinde daha da fazla özellik var ancak bunların geleceği oldukça belirsiz ve fikirler için yer tutucudan başka bir şey değiller. Örnekler arasında özel taşma davranışları, CSS söz dizimi uzantı API'si, yerel kaydırma davranışının uzantısı ve benzer iddialı şeyler yer alır. Bunlar, web platformunda daha önce mümkün olmayan şeyleri mümkün kılar.
Demolar
Demonun kodunu (polyfill kullanan canlı demo) açık kaynak olarak yayınladım.