CSS'nin nihayet görsel etkileşimler üzerindeki kontrolü geri alması, stilin, animasyonun ve erişilebilirliğin sorumluluğunu tam olarak olması gerektiği gibi üstlenmesi gerçeğini seviyorum. Bugün, yerel tarayıcı yetenekleri, ağır yükü JavaScript ana iş parçacığından uzaklaştırıp GPU'ya yakınlaştırmamıza olanak tanıyor. Tarayıcı motorunun performansı optimize etmesine izin vererek, sağlam, erişilebilir ve gelecekte kullanımdan kaldırılabilecek harici kitaplıklardan bağımsız kodlar oluştururken enerji ve işlem gücünden tasarruf ediyoruz.
3 boyutlu, modern düzen tekniklerimiz, klip yollarımız, dönüşümlerimiz, özel özelliklerimiz, kaydırmayla yönlendirilen animasyonlarımız, görünüm geçişlerimiz, @property'miz var ve neredeyse her şeyi, hatta otomatik yüksekliğe kadar canlandırabiliriz!
Ve elbette, yeni olmayan ancak resimler ve animasyonlar yoluyla web sitelerinin tamamını oluşturmamıza olanak tanıyan SVG var. Aşağıdaki örneği ele alalım: duyarlıdır, hafiftir, erişilebilirdir ve öncelikle CSS Grid + SVG tarafından desteklenmektedir.
Nasıl Önlem Alınmalı?
Yalnızca SVG kullanarak kullanıcı arayüzü de dahil olmak üzere tam bir video oyunu bile oluşturabiliriz:
Aşağıda, modern CSS'ye yönelik eksiksiz bir rehber değil, bir sitenin canlı hissetmesini ve hatırlanmasını istediğimde ulaştığım, fikir sahibi bir teknik seçkisi yer alıyor. Unutulmaz deneyimler yaratmanın birçok yolu vardır. Bazen sorunsuz bir şekilde tamamlanan bir form kadar basittir. Ancak burada ben yelpazenin ifade edici tarafıyla ilgileniyorum.
Detaylar ve Etkileri
İletişim Olarak Hareket: Niyetinizi Tanımlamak
Teknik tarafa geçmeden önce bir şeyi açıklığa kavuşturmak istiyorum: Sırf yapabiliyoruz diye bir şeyleri hareket ettirmemeliyiz.
Önemli Gelişmeler
Her şey iletişim kurar ve animasyonlarımız da bir istisna değildir. Niyetlerimizi aşırıya kaçmadan dar bir kapsamda tutabilmek için iletmek istediğimiz mesajı destekleyen hareketleri tasarlamaya zaman ayırmalıyız.
İşte bir sitenin tasarımını ve animasyonunu planlarken kullandığım bir metodoloji.
Mantar odaklı bir doğa etkinliği projesi üzerinde çalıştığımızı düşünün. Tasarım dili tamamen "havaya" bağlı olarak değişiyor: "Psychedelic Mantar Rave" satmak, ataların tıbbına odaklanan "Ruhsal Mantar İnzivası"ndan çok farklı.
Gelecekte Ne Bekleniyor?
Her tasarım kararı iletişim kurar. Amacımı ve kapsamımı tanımlamak için anahtar kelime listeleri dediğim şeyleri oluşturmayı seviyorum. Örneğin, işleri farklı seçeneklere ayırabilirim:
Seçenek A: Psikedelik Etkinlik
Görseller: Renkli, doygun, yüksek kontrastlı, illüstrasyonlar, çarpıtmalar
Uzmanların Görüşleri
Renkli, doygun, yüksek kontrastlı, çizimler, çarpıtmalar Hareket: Hızlı, çılgınca, öngörülemez, geçiş, ritmik, senkronize döngüler, hipnotik
Hızlı, çılgınca, öngörülemez, dönüşen, ritmik, senkronize döngüler, hipnotik Duygu: Eğlenceli, kaotik, enerjik, uyarıcı, şaşırtıcı
Eğlenceli, kaotik, enerjik, teşvik edici, şaşırtıcı Tipografi: Funk, “psych-rock”
Sistem Güvenliği
Funk, "psych-rock" Stil Referansları: Pop Art, 60'lar/70'ler op sanatı, rave ilanları
Sonuç ve Değerlendirme
Pop Art, 60'lar/70'ler op sanatı, çılgın el ilanları Aksiyonlar: Dans
Dans Ekstraları: Emojiler, filmler (ör. Las Vegas'ta Korku ve Nefret)
Teknik Analiz
Seçenek B: Manevi İnziva
Görseller: Toprak tonları, nötr tonlar, doygunluğu giderilmiş, fotoğraf ağırlıklı, doğa, boşluk
Toprak tonları, nötr tonlar, doygunluğu giderilmiş, fotoğraf ağırlıklı, doğa, boşluk Hareket: Yavaş, akıcı, organik, nefes alma, ince paralaks, düzgün kaydırma.
Yavaş, akıcı, organik, nefes alan, hafif paralaks, düzgün kaydırma. Duygu: Sakin, dingin, içe dönük, düşünceli, güvenli
Sakin, dingin, içe dönük, düşünceli, güvenli Tipografi: Zarif Serif, minimalist sans-serif, geniş aralık, okunaklı
Zarif Serif, minimalist sans-serif, geniş aralık, okunaklı Stil Referansları: İskandinav tasarımı, Japon Wabi-sabi, sağlıklı yaşam/spa estetiği, botanik kitapları
İskandinav tasarımı, Japon Wabi-sabi, sağlıklı yaşam/spa estetiği, botanik kitapları Eylemler: Nefes alma
Nefes Alma Ekstraları: İyileştirici sesler, film (örneğin, Ye Dua Et Sev)
Bu, tasarım ve animasyon kararlarıma rehberlik etmek için yaptığım türden bir egzersiz. Listeler, kullanmayı planladığım CSS özelliklerini ve bunların nasıl kullanılacağını seçmemde bana yardımcı olacak. Hatta bunları müşteriyle paylaşıyorum ve birlikte bir yön seçiyoruz.
Diyelim ki Seçenek A'yı tercih edelim ve unutulmaz kullanıcı deneyimleri yaratmak için temel bileşenler olduğunu düşündüğüm birkaç örneğe bakalım.
Bölünmüş Metin Animasyonları
Bu animasyonlar GSAP SplitText eklentisi sayesinde popüler hale geldi. Metni karaktere (veya isterseniz kelimelere veya satırlara) göre böler, böylece kademeli animasyonlar gibi ilginç metin efektleri oluşturabiliriz.
H O L < span style="--i:3">A
Bu yaklaşım “Hola”daki her harfi bir aralıkta sarar. Buradan, her bir yayılma alanı, aralıkları sırayla indeksleyen özel bir özellik ile satır içi stile dönüştürülür. Sibling-index() işlevi geniş tarayıcı desteği kazandığında bu çok daha kolaylaşacak bir şey.
Ancak şimdilik her özel özellik değeri, animasyon gecikmesini artıran ve her aralığı şaşırtan bir çarpan görevi görüyor. Bu durumda, yukarı doğru hareket ettikçe her karakterde solmaya başlarız.
.reveal-text span { animasyon: SlideUp 0,6 saniyelik ilerleme hızı; animasyon gecikmesi: calc(var(--i) * 0,1s); ekran: satır içi blok; opaklık: 0; dönüşüm: TranslateY(3rem); } @keyframes SlideUp { ila { opaklık: 1; dönüşüm: çeviriY(0); } }
Erişilebilirlik burada zor kısımdır. İçgüdü, aria-hidden='true' ile tüm bireysel kapsamları yardımcı teknolojiden gizlemek ve ekran okuyucular için tam kelimenin görsel olarak gizlenmiş bir versiyonunu eklemektir:
HOLA
.sr-only { konum: mutlak; genişlik: 1 piksel; yükseklik: 1 piksel; dolgu: 0; kenar boşluğu: -1 piksel; taşma: gizli; klip: rect(0, 0, 0, 0); beyaz boşluk: şimdirap; sınır: 0; }
Ancak uyaralım: Bu model tüm ekran okuyucularda iyi bir deneyimi garanti etmez. Adrian Roselli, GSAP'nin SplitText'ini sekiz ekran okuyucu ve tarayıcı kombinasyonunda test etti ve yalnızca ikisinde doğru çalıştığını gördü. Bu tekniği gönderirseniz, gerçek yardımcı teknolojiyle test edin.
Bu risk çok yüksek geliyorsa, Preethi'nin harf aralığı özelliğini kullanan, bilmeye değer çok akıllı bir alternatifi var. Karakterleri üst üste çökerten negatif değerleri kabul eder, DOM'a hiç dokunmadan gizler. Tekrar 0'a canlandırın ve erişilebilirlik ek yükü olmadan benzer bir ortaya çıkarma efekti elde edin.
Harika olurdu, ::nth-letter gibi bir sözde seçici, bireysel glifleri doğrudan CSS'den hedeflemek için ::first-letter'in ilk karakteri seçmesi gibi. Ama ne yazık ki, ::n'inci harf yok... en azından henüz.
Her animasyonda kullanıcının hareket tercihlerine saygı duymayı unutmayın:
@media (azaltılmış hareketi tercih eder: azalt) { .reveal-text span { animasyon: yok; /* veya daha yumuşak bir animasyon */ } }
CodePen Yerleştirme Geri Dönüşü
Uygulamak istediğimiz çok fazla metin ve farklı animasyonlar olduğunda çok fazla ölçeklenmeyebilir. Psychedelic olay için, metni SMIL ile bölmeyi denemek istedim ama çok ayrıntılıydı. Bu, yalnızca iki harfi canlandırmanın kodudur:
İşte kodun tamamı. Bunu sizin için yapacak bir yapay zekaya sahip olduğunuzda bunu yazmak daha kolaydır:
CodePen Yerleştirme Geri Dönüşü
Daha uzun metinler için GSAP gibi bir kitaplık size daha fazla kontrol sağlar ancak daha önce tartıştığımız aynı erişilebilirlik riskleri geçerlidir ve ekran okuyuculardaki sonuçlar tutarsızdır:
Tüm Hongos'un oğlu mágicos
const splitFirst = SplitText.create('.splitfirst', { type: "karakterler", }); const splitLast = SplitText.create('.splitlast', { type: "karakterler, çizgiler", maske: "satırlar" }); const tween = gsap.timeline() .from(splitFirst.chars, { xPercent: 100, kademelendirme: 0,1, opacity: 0, süre: 1, }) .from(splitLast.chars, { yPercent: 100, kademelendirme: 0,1, opacity: 0, süre: 1, });
Eğer o yola gitmiş olsaydık, B Seçeneği için bu güzel bir yaklaşım olurdu. Metin yavaş yavaş kaybolurken her şeyin ne kadar "sakin" hissettirdiğini görün.
CodePen Yerleştirme Geri Dönüşü
Maskeleme ve Kırpma klip yolu ve maske özellikleri, bir öğenin bölümlerini gizlememize olanak tanır, ancak bunlar temelde farklı prensiplerle çalışır. Kırpma ikili bir karardır: Pikseller ya tamamen görünürdür ya da tamamen kaybolmuştur; bu da onu tarayıcının oluşturmayı daha verimli bir şekilde optimize edebileceği çokgenler, daireler veya SVG yolları gibi temiz geometrik şekiller için doğru seçim haline getirir. Öte yandan maskeleme, parlaklık veya alfa kanalı değerlerini kullanır: beyaz ortaya çıkar, siyah gizler ve aradaki her şey kısmi şeffaflık üretir. Bu, onu yumuşak kenarlar, degrade soluklaşmalar ve düzensiz dokular için bir araç haline getirir. Çok karmaşık bir vektör şekliniz varsa, vektör klip yolu yerine maske kullanmanın daha performanslı olabileceğini unutmayın. Sarah Drasner'ın, birini diğerinin yerine kullanmanın ne zaman mantıklı olacağı konusunda güzel bir yazısı var.
Projemiz klip yolu için çok açık bir kullanım örneğidir. Clip-path: Circle(0%) ile başlayan bir daire şeklimiz var, bu da öğeyi görünmez kılar (kırpma dairesinin yarıçapı sıfırdır). Animasyonun süresi boyunca, çember(100%) şeklinde genişler; bu, çemberin merkezinden dışarı doğru büyüdükçe öğeyi tamamen ortaya çıkarır. Bu arada, opaklığın yardımıyla olayları solduruyoruz.
#gökkuşağı, #zemin, #mantar, #çiçekler { opaklık: 0; animasyon: maskAnim 2'nin ilerleme kolaylığı; } @keyframes maskAnim { 0%, 1% { klip-yolu: daire(0%); opaklık: 1; } %100 { klip yolu: daire(100%); opaklık: 1; } }
Not: %1 anahtar karesi, tarayıcının klip yolu enterpolasyonunu öğenin halihazırda sahip olabileceği değerden ziyade daire (%0) üzerinden başlatmasını sağlamak için vardır. Bu olmadan, bazı tarayıcılar başlangıçta beklenmedik bir şekilde atlayacaktır. Daha temiz bir alternatif, animasyon-doldurma modunu kullanmaktır: her ikisi de, animasyon başlamadan önce öğeyi başlangıç durumunda kilitler.
Buradan aynı animasyonu çizimimizdeki farklı SVG gruplarına uyguluyoruz:
Bu ne kadar psychedelic?!
CodePen Yerleştirme Geri Dönüşü
Kaydırma Odaklı Animasyonlar
Kaydırma odaklı animasyonlar harikadır çünkü bir animasyonun ilerleyişini, çalışan ve duran tipik bir zaman çizelgesi yerine kullanıcının kaydırma işlemine bağlayabiliyoruz.
Bunu hafif bir paralaks efekti gibi ince ve biraz "tuhaf" hareketler için kullanabiliriz. Bu durumda kullanıcıya yakın görünen nesnelerin, uzaktakilere göre daha hızlı hareket etmesini sağlayabiliriz.
CodePen Yerleştirme Geri Dönüşü
#estrellas, #arcoiris, .text-line, #fecha, #arco, #flores, #dir, #piso, #barras { animasyon: ikisini de yukarı taşı; animasyon-zaman çizelgesi: view(); } @keyframes moveUp { from { transform:translateY(var(--offset)); opaklık: 0; } - { transform:translateY(0); opaklık: 1; } } #estrellas { --offset: 10vh; } #arcoiris { --offset: 20vh; } #fecha { --offset: 45vh; } #arco { --offset: 50vh; } #dir { --offset: 50vh; } #flores { --offset: 65vh; } #piso { --offset: 85vh; } #barras { --offset: 90vh; }
Animation-timeline: view(), bir öğenin kaydırma portuna girdiği anda, kullanıcı kaydırdığında animasyonun başlaması ve görünümden çıktığında tamamen tamamlanması gerektiğini söylüyor. Nesnelerin farklı hızlarda hareket etmesini sağlamak için, daha önce metni bölmek için yaptığımız gibi, indekslenmiş --offset özel özelliğini kullanarak bunları farklı uzaklıklara yerleştiririz.
Bu daha zor ve performansa dikkat etmemiz gerekiyor. Layoutit gibi bir araç, tamamen CSS 3D ile oluşturulmuş bir voksel ve arazi oluşturucuya sahip olduğundan asansörün taşınmasına yardımcı olabilir. Yalnızca CSS Izgara katmanlarını kullanarak 3 boyutlu küpler oluşturan ve Canvas veya WebGL'nin karmaşıklığı olmadan dönüşüm sağlayan tam bir voksel motoru olan VoxCSS ile tamamlandığında daha da ileri gidebilir.
Kaydırma ve 3D efektlerin bir kombinasyonunu bir araya getirelim. A Seçeneği anahtar kelime listesindeki "hipnotik" ve "dans etme" fikirlerini destekleyen türden bir şey. Şuna bir göz atın:
CodePen Yerleştirme Geri Dönüşü
Burada, perspektif özelliğini kullanarak derinliği olan bir sahne oluşturdum ve ardından sahnenin içindeki tüm alt öğeleri transform-style: save-3d ile 3 boyutlu bir alana sardım. Bu şekilde, tüm alt görüntü öğeleri derinlik ekseni (veya z ekseni) boyunca döner ve çevrilir.
Bunu transform: rotaryY kullanan kaydırma odaklı bir animasyona bağlayalım:
.scene { perspektif: 1200 piksel; } .img-wrapper { dönüşüm stili: koru-3d; animasyon: RotateImg doğrusal; animasyon zaman çizelgesi: kaydırma(); > img { transform: döndürY(270deg)translate3d(0, 50px, var(--distance)); } > img:nth-child(2) { transform: RotateY(180deg) trans late3d(0, 50px, var(--distance)); } } /* vb. */ @keyframes rotaryImg { to { transform: rotaryY(360deg); } }
imleç en çok kullanılmayan CSS özelliklerinden biri olabilir. Kullanabileceğimiz birçok imleç türü var, ancak bu konuda ne kadar ileri gidilebileceğine dair kesinlikle görüşler var.
Ve bunu, görüntülerle oynamak için kullanabiliriz, kullanıcı bunların üzerine geldiğinde farklı kaplarda farklı imleçler görüntüleyebiliriz. Özellik herhangi bir raster görüntüyü desteklemesine rağmen, şeffaflık desteği için kişisel olarak bir SVG ve PNG görüntüsü kullanırdım.
İmleç boyutlarının tarayıcıya göre değiştiğini belirtmekte fayda var: Firefox özel imleçleri 32×32 piksel boyutunda sınırlarken Chrome 128×128 piksele kadar destekler. Çoğu tarayıcı, yüksek DPI (retina) ekranlarda 32×32 pikselden büyük imleçleri görüntülemeyi reddeder veya küçültür. Tutarlılığı sağlamak için imlecinizi 32×32 piksel boyutunda tutmak en güvenli seçimdir.
.kutu1 { imleç: url(data:image/png;base64,iVBORw0KGgoAAAAANSUhEUgAAAB0AAAAZCAMAAAD63NUrAAAACVBMVEX///8AAAD///9+749PAAAAAXRSTlMAQObYZgAAAFZJREFUeNqdzksK wDAIAFHH+x+6lIYOVPOhs5OHJnES/5UkYKEkU7xjijSIm50iFh4fAXgYDd/yumVVRSwsqq/nRA3xVK0oo06d5U6DpQZ7PV7lMxH7LkaQAbYFwryzAAAAAElFTkSuQmCC),otomatik; }
En geniş düzeyde tarayıcı desteği sağlamak için birden fazla yedek bile ayarlayabiliriz:
body { imleç: url('görüntünün yolu.png'), url('görüntünün yolu-2.svg'), url('görüntünün yolu-3.jpeg'), otomatik; }
Bu harika bir şey olsa da, bunun gibi varsayılan web davranışını değiştiren bir şey için erişilebilirliği aklımızda tutmalıyız. Özel imleçlerin toptan satış yerine çok spesifik öğelere uygulanması eğlenceli olabilir.
CodePen Yerleştirme Geri Dönüşü
Bonus: Çapa Konumlandırma
Bitirmeden önce bir şey daha. Kevin Powell'ın demosundan esinlenerek CSS Anchor Positioning ile oynuyorum. Bunu, her bir öğe için bir sözde öğe eklemek yerine, o anda üzerinde durulan bir öğeye tek bir sözde öğe eklemek için kullanabiliriz. Başka bir deyişle, tek bir öğe oluştururuz ve onu, vurgulama kartları gibi, üzerine gelinen bir öğeye sabitleriz:
CodePen Yerleştirme Geri Dönüşü
Bu, kartlar arasında fareyle üzerine gelme durumunu değiştirebilmek gibi ilginç olasılıkların önünü açıyor. Bu durumda, Kolaylaştırma Sihirbazı'nın yardımıyla bu doğal sıçramayı elde etmek için lineer() işlevini kullanıyorum.
Unutulmaz web deneyimleri yaratmanın önündeki teknik engeller artık büyük ölçüde ortadan kalktı. Umarım burada ele aldığımız her şey, ek JavaScript ihtiyacını tamamen ortadan kaldıran modern CSS özellikleriyle ne kadar ileri gidebileceğimiz konusunda size bir fikir verir. Her zamankinden daha fazla olanağımız var ve bunların tümünü, geçmiş günlerdeki gibi karmaşık teknik ek yüklere ihtiyaç duymadan gerçekleştiriyoruz.
Peki bu mümkün mü diye sormak yerine en önemli soru şu oluyor: Bu hareket daha iyi bir hikaye anlatıyor mu? Evet ise gönderin. Bu araçları yapabildiğiniz için değil, daha iyi, aynı zamanda erişilebilir ve performanslı bir hikaye anlatmanıza yardımcı oldukları için kullanın.
Ve tabii ki buradaki her şey bunu yapmanın birkaç yolundan ibaret. Peki işinizde ne tür unutulmaz deneyimler kullandınız? Veya diğer sitelerde neler gördünüz?