CSS'nin ne kadar iş yaptığı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. Şimdiye kadar, web geliştiricileri topluluğu olarak bu sihri yalnızca tanıyabildik ve gözlemleyebildik. Kendi sihrimizi bulmak istersek ne yapalım? Peki ya sihirbaz olmak istersek?
Houdini'ye girin!
Houdini görev gücünde; CSS motorunun belirli bölümlerini web geliştiricilerine sunmak için birlikte çalışan Mozilla, Apple, Opera, Microsoft, HP, Intel ve Google mühendislerinden oluşur. Görev gücü, gerçek web standartları olmaları amacıyla bunların W3C tarafından kabul edilmesini sağlamak amacıyla bir taslak koleksiyonu üzerinde çalışmaktadır. Kendilerine birkaç üst düzey hedef belirlediler ve bunları belirli alt düzey spesifikasyon taslaklarına dönüştürdüler.
Biri "Houdini"den bahsettiğinde genellikle bu taslakları derleme kastediliyor. Yazma sırasında taslak listesi eksik ve taslakların bazıları yalnızca yer tutucudur.
Spesifikasyonlar
İş 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. "İş programını" okurken Web İşçileri aklınıza geldiyse haksız sayılmazsınız. Kavramlar birbiriyle birçok şekilde çakışıyor. Peki, zaten çalışanlarımız varken neden yeni bir şey?
Houdini'nin amacı, web geliştiricilerin kendi kodlarını CSS motoruna ve benzer 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 kare çalıştırılması gerektiğini varsaymak muhtemelen gerçekçi değildir. Bazılarının tanımı gereklidir. Web çalışanı 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. İş akışları, imzaları iş akışı türüne göre önceden tanımlanmış olan 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 (spec)
Paint API, Chrome 65'te varsayılan olarak etkindir. Ayrıntılı girişi okuyun.
Birleştirici iş akışı
Burada açıklanan API artık kullanılmıyor. Birleştirme iş akışı yeniden tasarlanmıştır ve artık "Animasyon İş Akışı" olarak önerilmektedir. API'nin mevcut yinelemesi hakkında daha fazla bilgi edinin.
Birleştirici iş akışı spesifikasyonu WICG'ye taşınmış ve yinelenecek olsa da beni en çok heyecanlandıran özellik budur. Bazı işlemler CSS motoru tarafından bilgisayarınızın grafik kartı aracılığıyla dış kaynaklı olarak yapı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 bağlı olarak bazı dallara ve alt ağaçlara kendi katmanlarını vermeye karar verir. Bu alt ağaçlar kendi üzerine boyar (belki gelecekte bir boya işçisi kullanarak). Son adım olarak, şu anda boyanmış olan tüm bu katmanlar, z endekslerine, 3D dönüştürmelere ve benzeri ölçütlere uygun şekilde üst üste yığılır ve ekranınızda görünür olan son resmi elde edilir. Bu işlem birleştirme 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 kendi kendine yeniden boyanmasını gerektirmemesidir. Bunun yerine, önceki karedeki katmanları yeniden kullanabilir ve birleştiriciyi güncellenen kaydırma konumuyla yeniden çalıştırabilirsiniz. Bu sayede işlemler hızlanır. Bu, 60 fps'ye ulaşmamıza yardımcı olur.
![Birleştirici iş akışı.](https://developer.chrome.google.cn/static/docs/css-ui/houdini/image/compositor-worklet-a5eb4330b62ac.png?authuser=5&hl=tr)
Adından da anlaşılacağı gibi, birleştirici iş akışı, birleştiriciyi bağlamanızı ve bir öğenin daha önce boyanmış olan katmanının diğer katmanların üzerine yerleştirilme ve katmanlandırılma şeklini etkilemenizi sağlar.
Biraz daha ayrıntılı belirtmek gerekirse, tarayıcıya belirli bir DOM düğümü için birleştirme işlemine dahil etmek istediğinizi belirtebilirsiniz 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 her karede kodunuz çağrılır. Katman dönüşümünü manipüle ederek ve özelliklerini (opacity
gibi) değiştirerek katmanınızı taşıyabilir ve 60 fps'de gösterişli şeyler yapabilirsiniz.
Birleştirici iş programını kullanarak paralaks kaydırmaya ilişkin eksiksiz bir uygulamayı 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ş akışı için bir polyfill 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 spesifikasyon taslağı önerildi. Özelliğin devreye girmesine daha az zaman kaldı.
Bu yöntemin spesifikasyonu pratik olarak boş olsa da konsept ilgi çekici: Kendi düzeninizi yazın! Düzen iş akışının, display: layout('myLayout')
işlemini yapmanızı ve bir düğümün alt öğelerini düğümün kutusunda düzenlemek için 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 uygulama çalıştırmaktan daha yavaştır ancak köşeleri kesmek performans artışı 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 kullanılmaz. z-index
öğeleri veya öğeler hiçbir zaman örtüşmez ya da herhangi bir sınır veya taşmaya sahip değildir. Yeniden düzenlemeyle ilgili tüm bu kontrolleri atlayabilmek
performansı artırabilir.
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 çözmeyi yeni öğrendiğimiz bir soruna yöneliktir. Bir JavaScript satırıyla örnekleyeyim:
$('#someDiv').style.height = getRandomInt() + 'px';
Matematik işlemi gerçekleştiriyoruz. Bir sayıyı dizeye dönüştürüyoruz. Böylece, tarayıcının bu dizeyi ayrıştırması ve CSS motoru için tekrar bir sayıya dönüştürmesi yeterlidir. Bu durum, JavaScript ile dönüşümleri değiştirdiğinizde daha da çirkinleşir. Başka yok! CSS biraz yazacak.
Bu taslak, daha olgun metodolojilerden biridir ve şu anda polyfill üzerinde çalışılmaktadır. (Sorumluluk reddi beyanı: Çoklu dolguyu kullanmak elbette daha da fazla işlem yükü ekler. Buradaki önemli nokta, API'nin ne kadar kullanışlı olduğunu göstermek.)
Dizeler yerine, her CSS özelliğinin kendi anahtarı ve karşılık gelen değer türüne sahip olduğu bir öğenin StylePropertyMap
üzerinde çalışacaksınız. width
gibi özelliklerin değer türü olarak LengthValue
kullanılır. LengthValue
; em
, rem
, px
, percent
vb. gibi tüm CSS birimlerinin sözlüğüdür. height: calc(5px + 5%)
ayarlanırsa LengthValue{px: 5, percent: 5}
elde edilir. box-sizing
gibi bazı özellikler sadece 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 Özellikleri'ni (veya resmi olmayan "CSS Değişkenleri") biliyor musunuz? Bunlar onlar gibi ama türleri de var. Şimdiye kadar, değişkenler yalnızca dize değerlerine sahip olabiliyordu ve basit bir ara ve değiştir yaklaşımından yararlanabiliyordu. Bu taslak, değişkenleriniz için yalnızca tür belirtmenize değil, aynı zamanda 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ınan bir diğer unsurdur.
["--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ğı üzeredir. 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? Çok şey talep edildi ve Houdini sonunda bu dilekleri yerine getirmesi gerekiyor.
Bir saniye, hepsi bu kadar da değil!
Houdini'nin taslaklar listesinde daha da fazla spesifikasyon var, ancak bunların geleceği henüz belli değil. Bunlar yalnızca fikir edinmek için 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 benzer iddialı şeyler yer alır. Bunlar, web platformunda daha önce mümkün olmayan şeyleri mümkün kılar.
Demolar
Demo kodunu açık kaynaklı hale getirdim (polyfill kullanarak canlı demo).