Animasyonu yüksekliğe getir: auto; (ve diğer doğal boyutlandırma anahtar kelimeleri)

Uzunluklardan doğal boyutlandırma anahtar kelimelerine kadar yumuşak geçişler ve animasyonlar sağlamak için interpolate-size özelliğini veya calc-size() işlevini kullanın.

Yayınlanma tarihi: 17 Eylül 2024

Giriş

Sık istenen bir CSS özelliği, height: auto için animasyon oluşturma olanağıdır. Bu isteğin küçük bir varyasyonu, height yerine width mülkünün veya min-content, max-content ve fit-content gibi anahtar kelimelerle temsil edilen diğer doğal boyutlardan herhangi birine geçiş yapılmasıdır.

Örneğin, aşağıdaki demoda fareyle simgelerin üzerine geldiğinizde etiketlerin doğal genişliklerine sorunsuz bir şekilde animasyonla ulaşması iyi olur.

Kullanılan CSS şu şekildedir:

nav a {
    width: 80px;
    overflow-x: clip;
    transition: width 0.35s ease; /* 👈 Transition the width */

    &:hover,
    &:focus-visible {
        width: max-content; /* 👈 Doesn't work with transitions */
    }
}

width mülkünde geçiş için bir transition ve :hover üzerinde width: auto bildirilmiş olsa bile sorunsuz bir geçiş gerçekleşmez. Bunun yerine, ani bir değişiklik olur.

interpolate-size ile, doğal boyutlandırma anahtar kelimeleri ile bu anahtar kelimeler arasında animasyon kullanın

Tarayıcı desteği

  • Chrome: 129.
  • Edge: Desteklenmez.
  • Firefox: Desteklenmez.
  • Safari: Desteklenmez.

Kaynak

CSS interpolate-size mülkü, CSS doğal boyutlandırma anahtar kelimelerinin animasyonlarına ve geçişlerine izin verilip verilmeyeceğini kontrol etmenizi sağlar.

Varsayılan değeri numeric-only olan bu parametre, enterpolasyonu etkinleştirmez. Özelliği allow-keywords olarak ayarlarken, tarayıcının bu anahtar kelimeleri animasyonlu olarak gösterebileceği durumlarda uzunluklardan CSS doğal boyutlandırma anahtar kelimelerine doğru aralıklarla doldurma işlemini etkinleştirirsiniz.

Spesifikasyona göre:

  • numeric-only: <intrinsic-size-keyword> değerleri ara değerle doldurulamaz.
  • allow-keywords: Biri <intrinsic-size-keyword>, diğeri <length-percentage> olan iki değer için kesme noktası belirlenebilir. […]

interpolate-size özelliği devralan bir özellik olduğundan, dokümanın tamamı için doğal boyutlandırma anahtar kelimelerine ve bu anahtar kelimelerden geçiş yapmayı etkinleştirmek için bunu :root üzerinde tanımlayabilirsiniz. Bu, önerilen yaklaşımdır.

/* Opt-in the whole page to interpolate sizes to/from keywords */
:root {
    interpolate-size: allow-keywords; /* 👈 */
}

Aşağıdaki demoda bu kural koda eklenmiştir. Sonuç olarak, width: auto'e gelen ve width: auto'den giden animasyonlar sorunsuz çalışır (destek verilen tarayıcılarda):

Seçiciyi daraltarak kaydolma işleminin erişimini sınırlama

allow-keywords etkinleştirmesini yalnızca dokümanınızın bir alt ağacıyla sınırlamak istiyorsanız seçiciyi :root'ten yalnızca hedeflemek istediğiniz öğeye ayarlayın. Örneğin, sayfanızın <header> öğesi bu tür geçişlerle uyumlu değilse etkinleştirmeyi yalnızca <main> öğesi ve alt öğeleriyle sınırlandırabilirsiniz.

main { /* 👈 Scope the opt-in to only <main> and its descendants */
    interpolate-size: allow-keywords;
}

Boyutlandırma anahtar kelimeleri arasında varsayılan olarak animasyona neden izin verilmiyor?

Bu etkinleştirme mekanizmasıyla ilgili yaygın bir geri bildirim, tarayıcıların varsayılan olarak doğal boyutlandırma anahtar kelimelerinden uzunluklara geçişlere ve animasyonlara izin vermesi gerektiğidir.

Bu davranışı etkinleştirme seçeneği, özellik geliştirilirken araştırıldı. Çalışma grubu, birçok stil sayfasında doğal boyutlandırma anahtar kelimelerinin (auto veya min-content gibi) animasyonlu olamayacağını varsaydığı için bu özelliğin varsayılan olarak etkinleştirilmesinin geriye dönük uyumlu olmadığını tespit etti. Ayrıntıları ilgili CSS Çalışma Grubu sorunuyla ilgili bu yorumda bulabilirsiniz.

Bu nedenle mülk etkinleştirilmiştir. Devralınabilir özelliği sayesinde, bir belgenin tamamını etkinleştirmek, daha önce ayrıntılı olarak açıklandığı gibi :root üzerinde yalnızca bir interpolate-size: allow-sizes beyanı olur.

calc-size() ile doğal boyutlandırma anahtar kelimeleri arasında animasyonlu geçiş yapma

Tarayıcı desteği

  • Chrome: 129.
  • Edge: 129.
  • Firefox: Desteklenmez.
  • Safari: desteklenmez.

Kaynak

Doğal boyutlandırma anahtar kelimeleri arasında ve bu anahtar kelimelerden diğer anahtar kelimelere doğru interpolasyonu etkinleştirmenin bir diğer yolu da calc-size() işlevini kullanmaktır. Matematiğin doğal boyutlar üzerinde güvenli ve iyi tanımlanmış bir şekilde yapılmasını sağlar.

İşlev, sırasıyla iki bağımsız değişkeni kabul eder:

  • Hesaplama boyutu temeli. Bu hem <intrinsic-size-keyword> hem de iç içe yerleştirilmiş bir calc-size() olabilir.
  • Hesaplama boyutu temelini kullanarak hesaplamalar yapmanıza olanak tanıyan hesaplama boyutu hesaplaması. Hesaplanmış boyut temelini belirtmek için size anahtar kelimesini kullanın.

Aşağıda bazı örnekler verilmiştir:

width: calc-size(auto, size);        // = the auto width, unaltered
width: calc-size(min-content, size); // = the min-content width, unaltered

Orijinal demoya calc-size() eklendiğinde kod şu şekilde görünür:

nav a {
    width: 80px;
    overflow-x: clip;
    transition: width 0.35s ease;

    &:hover,
    &:focus-visible {
        width: calc-size(max-content, size); /* 👈 */
    }
}

Görsel olarak sonuç, interpolate-size kullanıldığında elde edilen sonuçla tamamen aynıdır. Bu durumda interpolate-size kullanmanız gerekir.

calc-size()'ün en iyi özelliği, hesaplama yapabilmesidir. interpolate-size ile bu işlem yapılamaz:

width: calc-size(auto, size - 10px); // = The auto width minus 10 pixels
width: calc-size(min-content, size + 1rem); // = The min-content width plus 1rem
width: calc-size(max-content, size * .5);   // = Half the max-content width

Örneğin, bir sayfadaki tüm paragrafların boyutunun 50px'e en yakın katına ayarlanmasını istiyorsanız aşağıdakileri kullanabilirsiniz:

p {
    width: calc-size(fit-content, round(up, size, 50px));
    height: calc-size(auto, round(up, size, 50px));
}

calc-size(), hesaplama boyutu tabanları aynı olan iki calc-size() arasında da enterpolasyon yapmanıza olanak tanır. Bu da interpolate-size ile yapılamaz.

#element {
    width: min-content; /* 👈 */
    transition: width 0.35s ease;

    &:hover {
        width: calc-size(min-content, size + 10px); /* 👈 */
    }
}

calc() içinde <intrinsic-size-keyword> öğesine neden izin verilmiyor?

calc-size() ile ilgili olarak sıklıkla sorulan sorulardan biri, CSS Çalışma Grubu'nun calc() işlevini doğal boyutlandırma anahtar kelimelerini destekleyecek şekilde neden ayarlamadığıdır.

Bunun nedenlerinden biri, hesaplama yaparken doğal boyutlandırma anahtar kelimelerini karıştırmanıza izin verilmemesidir. Örneğin, geçerli görünen bir calc(max-content - min-content) yazmak cazip gelse de gerçekte öyle değildir. calc-size(), calc()'ten farklı olarak ilk bağımsız değişkeni olarak yalnızca tek bir <intrinsic-size-keyword> kabul ettiğinden doğruluğu zorunlu kılar.

Bir diğer sebep de bağlam farkındalığıdır. Bazı düzen algoritmalarının belirli içsel boyutlandırma anahtar kelimeleri için özel bir davranışı vardır. calc-size(), <length> değil, içsel bir boyutu temsil edecek şekilde açıkça tanımlanmış. Bu sayede bu algoritmalar, calc-size(<intrinsic-size-keyword>, …)<intrinsic-size-keyword> olarak değerlendirerek söz konusu anahtar kelimeye yönelik özel davranışını koruyabilir.

Hangi yaklaşımı kullanmalısınız?

Çoğu durumda :root üzerinde interpolate-size: allow-keywords tanımlayın. Esasen tek satırlık bir kod olduğundan, animasyonu doğal boyutlandırma anahtar kelimeleri arasında etkinleştirmenin en kolay yoludur.

/* Opt-in the whole page to animating to/from intrinsic sizing keywords */
:root {
    interpolate-size: allow-keywords; /* 👈 */
}

Bu kod, desteklemeyen tarayıcılarda geçiş kullanılmadığı için iyi bir aşamalı geliştirmedir.

Hesaplama yapma gibi işlemler üzerinde daha ayrıntılı kontrole ihtiyacınız olduğunda veya yalnızca calc-size() tarafından kullanılabilen bir davranışı kullanmak istediğinizde calc-size()'ü kullanabilirsiniz.

#specific-element {
    width: 50px;

    &:hover {
        width: calc-size(fit-content, size + 1em); /* 👈 Only calc-size() can do this */
    }
}

Ancak kodunuzda calc-size() kullanmanız, calc-size()'ü desteklemeyen tarayıcılar için yedek seçenekler eklemenizi gerektirir. Örneğin, ekstra boyut bildirimleri ekleme veya @supports kullanarak özellik algılamaya dönme.

width: fit-content;
width: calc-size(fit-content, size + 1em);
       /* 👆 Browsers with no calc-size() support will ignore this second declaration,
             and therefore fall back to the one on the line before it. */

Diğer demolar

interpolate-size: allow-keywords'ten yararlanan diğer bazı demoları aşağıda bulabilirsiniz.

Bildirimler

Aşağıdaki demo, bu @starting-style demosunun bir çatalıdır. Kod, yükseklikleri farklı olan öğelerin eklenmesine izin verecek şekilde ayarlandı.

Bunu yapmak için sayfanın tamamı anahtar kelime boyutu için kesme işlemini etkinleştirir ve her .item öğesindeki height auto olarak ayarlanır. Aksi takdirde kod, çatallanmadan öncekiyle aynıdır.

:root {
    interpolate-size: allow-keywords; /* 👈 */
}

.item {
    height: auto; /* 👈 */

    @starting-style {
        height: 0px;
    }
}

<details> öğesine animasyon ekleme

Bu tür bir enterpolasyonu kullanmak istediğiniz tipik bir kullanım alanı, bir açıklama widget'ını veya özel akordeonu açarken animasyonlu hale getirmektir. HTML'de bunun için <details> öğesini kullanırsınız.

interpolate-size: allow-keywords ile oldukça ilerleyebilirsiniz:

@supports (interpolate-size: allow-keywords) {
    :root {
        interpolate-size: allow-keywords;
    }
    
    details {
        transition: height 0.5s ease;
        height: 2.5rem;
        
        &[open] {
            height: auto;
            overflow: clip; /* Clip off contents while animating */
        }
    }
}

Ancak göreceğiniz gibi animasyon yalnızca açıklama widget'ı açıldığında çalışır. Bu ihtiyacı karşılamak için Chrome, bu yılın ilerleyen dönemlerinde Chrome'da kullanıma sunulacak ::details-content sözde sınıf üzerinde çalışıyor (bu konu gelecek bir yayında ele alınacaktır). interpolate-size: allow-keywords ve ::details-content'ü birleştirerek her iki yönde de animasyon elde edebilirsiniz: