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

Uzunluklardan doğal boyutlandırma anahtar kelimelerine ve geriye sorunsuz geçişler ve animasyonlar sağlamak için interpolate-size mülkünü 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üne geçiş yapmak veya min-content, max-content ve fit-content gibi anahtar kelimelerle temsil edilen diğer içsel boyutlardan herhangi birine geçiş yapmaktı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, değişiklik ani olur.

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

Browser Support

  • Chrome: 129.
  • Edge: 129.
  • Firefox: not supported.
  • Safari: not supported.

Source

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.

Özelliğe 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 mülkü devralınan bir mülk olduğundan, dokümanın tamamı için doğal boyutlandırma anahtar kelimelerine geçişi ve bu anahtar kelimelerden geçişi etkinleştirmek üzere :root üzerinde beyan edebilirsiniz. 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 gidip gelen animasyonlar sorunsuz çalışır (destekli 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ınma ö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

Browser Support

  • Chrome: 129.
  • Edge: 129.
  • Firefox: not supported.
  • Safari: not supported.

Source

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. Bu sayede, matematiksel işlemlerin doğal boyutlarda güvenli ve iyi tanımlanmış bir şekilde yapılmasına olanak tanır.

İşlev şu sırayla iki bağımsız değişken kabul eder:

  • <intrinsic-size-keyword> veya iç içe yerleştirilmiş calc-size() olabilen bir hesaplanmış boyut.
  • calc-size tabanını kullanarak hesaplama yapmanıza olanak tanıyan bir calc-size 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>'e 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 ancak aslında geçerli olmayan calc(max-content - min-content) yazmak isteyebilirsiniz. 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 neden de bağlam bilincidir. Bazı düzen algoritmalarının belirli doğal boyutlandırma anahtar kelimeleri için özel bir davranışı vardır. calc-size(), <length> değil, doğal bir boyutu temsil etmek üzere açıkça tanımlanır. 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ğu için, 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, ek boyut beyanları eklemek veya @supports kullanarak özellik algılamaya geri dönmek.

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, farklı yükseklikteki öğ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 çok şey yapabilirsiniz:

@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: