Yaklaşık 15 yıllık deneyime sahip bir ön uç geliştirici olarak web geliştirmenin evrimine ilk elden tanık oldum. Benim için, değiştirilmiş dosyaların FTP aracılığıyla yüklendiği günlerden (evet, GitHub 15 yıl önce piyasaya sürüldü, ancak ben onu yalnızca 2011'de keşfettim) duyarlı arayüzlerin, kullanıcı arayüzü kitaplıklarının ve doğrudan buradan oluşturulan web sitelerinin modern çağına kadar çok uzun bir yol kat etti. Figma.
Ancak yine de aşağıdaki gibi iç içe geçmiş stiller kullanan projelerle karşılaşıyorum:
.some-class ul li div a { /* some style */ }
veya,
#nav .nav-link svg { /* some style */ }
Şok edici görünebilir, ancak bu tür kodlama uygulamaları multimilyon dolarlık, hızla büyüyen projelerden mütevazi girişimlere kadar her şeye yayılıyor.
Bu yaklaşımın neden sorun yaratabileceğini inceleyelim.
Derinlemesine iç içe geçmiş stiller, özellikle büyük bir projeniz varsa, genellikle stil çatışmalarına yol açar. Basamaklı bir stil sayfası olarak CSS, aşağıya doğru basamaklanır ve özelliklerine bağlı olarak öğelere uygulanır. Derinlemesine iç içe geçmiş stiller, özgüllükleri nedeniyle istemeden diğer stilleri geçersiz kılabilir.
Bu örneği düşünün:
.some-class ul li div a { color: red; } ... .some-class a { color: blue; }
.some-class
dosyasındaki tüm bağlantıların mavi olmasını bekleyebilirsiniz. Bununla birlikte, ilk kuralın daha spesifik olması nedeniyle ul > li > div
içinde yer alan herhangi bir bağlantı mavi değil kırmızı olacaktır. Bu, beklenmedik görsel tutarsızlıklara ve hata ayıklamada çok fazla zaman kaybına neden olabilir.
CSS'deki özgüllük kavramını (veya stillerin 'ağırlığını') anlamak, derin yuvalamanın neden sorun yaratabileceğini anlamak açısından çok önemlidir. Belirlilik, tek bir öğe için birden fazla kuralın rekabet etmesi durumunda hangi CSS kuralının uygulanacağını belirler. Seçicilerin türüne ve miktarına göre hesaplanır.
Özgüllük dört kategorili bir ağırlıklandırma sistemine göre hesaplanır:
Burada kuralı göz önünde bulundurun:
body #content .data img:hover { /* some style */ }
Spesifiklik 0 1 2 2'dir . Bu bir kimlik ( #content ), iki sınıf ( .data ve :hover ) ve iki öğedir ( body ve img ).
Şimdi kuralı düşünün:
#nav .nav-link svg { /* some style */ }
Buradaki özgüllük 0 1 1 1'dir . Bu bir kimlik ( #nav
), bir sınıf ( .nav-link
) ve bir öğedir ( svg
).
Özgüllük, geleneksel ondalık sayılar gibi "aktarma" sisteminde çalışmaz. Örneğin, 0 1 0 11 özgüllüğüne sahip bir seçici, ondalık sistemde 11 ve 1+1 eşdeğer olsa da 0 1 1 1 özgüllüğüne eşit değildir.
Son olarak, evrensel seçicinin ( *
), birleştiricilerin ( +
, >
, ~
, ' ') ve olumsuzlama sözde sınıfının ( :not()
) özgüllük üzerinde hiçbir etkisi yoktur. Ancak :not()
argümanının içinde seçiciler her zamanki gibi sayılır.
Görsel öğrenenler için CSS Özgüllüğü ile ilgili bu videoyu öneriyorum.
CSS özgüllüğünü ve bunun nasıl hesaplandığını anlamak, daha iyi, daha öngörülebilir CSS yazmanıza ve stiller beklendiği gibi uygulanmadığında sorunların hatalarını ayıklamanıza olanak tanır.
!important
Kural ve Özellik Bazen geliştiriciler, CSS özgüllüğü çatışmalarıyla ilgili zorluklarla karşılaştıklarında !important
kuralını kullanmaya başvururlar. Bu kural bir CSS özelliğini son derece spesifik hale getirir, yani hemen hemen tüm diğer bildirimleri geçersiz kılacaktır.
Örneğin:
#nav .nav-link svg { color: blue; } .nav-link svg { color: red !important; }
Kimlik seçici nedeniyle ilk kuralın özgüllüğü daha yüksek olmasına rağmen, ikinci kuraldaki !important
nedeniyle svg
rengi kırmızı olacaktır.
!important
belirlilik sorunlarıyla uğraşırken hızlı bir çözüm olsa da, bunun kapsamlı bir şekilde kullanılması önerilmez. Aşırı kullanım sürdürülebilirliği, öngörülebilirliği ve performansı etkileyebilir. Daha büyük projelerde !important
aşırı kullanımı genellikle CSS özgüllüğünün yönetilmesinde zorluk yaşandığını gösterir. !important
başvurmak yerine, CSS'nizi yeniden düzenlemek ve aşırı spesifik seçicilerin kullanımını azaltmak için zaman harcamak genellikle daha iyidir.
Hemen ürününüzü kontrol edebilirsiniz 🙂. Benimkini kontrol ettim:
!important
cazip bir hızlı çözüm olsa da; fındık kırmak için balyoz kullanmaya benzer. Daha sürdürülebilir bir yaklaşım, seçicilerinizi olabildiğince basit ve düz tutmaktır; bu, CSS'nizin gelecekte anlaşılmasını, yönetilmesini ve genişletilmesini kolaylaştırır. Ve unutmayın, !important
bir savaşı kazanmanın en iyi yolu, ilk etapta bir savaş başlatmamaktır.
Derinlemesine iç içe geçmiş stillerle ilgili diğer bir sorun, tarayıcı oluşturma üzerindeki performansın etkisidir. Bir tarayıcı, bir öğeye stiller uyguladığında, anahtar seçiciden (örneklerimizde a
ve svg
) başlayarak ve bir eşleşme bulana veya en üste ulaşana kadar atalar arasında ilerleyerek DOM'u sağdan sola doğru hareket ettirir. Stil ne kadar iç içe olursa bu geçiş o kadar uzun sürer; bu da büyük ölçekli projelerde performansı etkileyebilir ve sayfa yükleme sürelerini yavaşlatabilir.
Aşağıdaki gibi bir CSS kuralı belirttiğinizde:
.some-class ul li a { /* some style */ }
Bu kuralı ağacın en altından ( a
etiketinden) başlayarak ve ağaç boyunca ( li
, ul
ve .some-class
yoluyla) yukarıya doğru çalışarak görselleştirebilirsiniz.
Tarayıcı ilk önce tüm (yani TÜM) a
elemanlarını arayacak, ardından bu a
etiketlerinin li
elemanlarının içinde olup olmadığını kontrol edecektir. Daha sonra bu li
elemanlarının ul
içinde olup olmadığını kontrol edecek ve son olarak bu ul
.some-class
sınıfına sahip bir elemanın içinde olup olmadığını kontrol edecek.
Tarayıcılar CSS seçicilerini bu şekilde okur ve karmaşık seçicilerin sayfanın daha yavaş oluşturulmasına yol açmasının nedeni budur. Tarayıcının, belirtilen kurala uyup uymadığını görmek için her öğe için birden fazla kontrol yapması gerekir. Kural ne kadar derin olursa, tarayıcının o kadar fazla kontrol yapması gerekir ve bu da performansı etkileyebilir.
CSS Modülleri, CSS'yi üzerinde çalıştığınız bileşene göre yerel olarak belirlenen ayrı modüller halinde yazmanıza olanak tanır. Bu, bir CSS modülündeki stillerin yalnızca söz konusu modüle uygulanabileceği ve dışarı sızmayacağı veya sayfadaki diğer öğeleri etkilemeyeceği anlamına gelir.
Stil kapsüllemesini sağlamak için CSS Modüllerinin karma sınıf adlarını nasıl kullandığını keşfedelim. CSS Modüllerini kullanırken, CSS dosyanızda tanımladığınız sınıf adlarına derleme zamanında karma işlemi uygulanacaktır. Bu karma, bileşeninize karşılık gelen benzersiz bir sınıf adı oluşturur. Bir örneğe bakalım:
Şu şekilde tanımlanmış bir CSS Modülünüz olduğunu varsayalım:
/* Button.module.css */ .button { color: white; background-color: blue; }
Ve bunu bileşeninizde şu şekilde kullanırsınız (styles nesnesini styles
yerine s
olarak içe aktarmayı tercih ederim; yazma süresinden tasarruf sağlayan ve kodlama verimliliğini artıran hızlı bir ipucu):
import React from 'react'; import s from './Button.module.css'; const Button = () => { return ( <button className={s.button}>Click me</button> ); }; export default Button;
Uygulamanız derlendiğinde, oluşturulan HTML'niz şunun gibi görünebilir:
<button class="Button_button__3FQ9Z">Click me</button>
Bu durumda Button_button__3FQ9Z
, CSS Modülünüzden oluşturulan karma sınıf adıdır. Hash'in tam yapısının ve uzunluğunun proje yapılandırmanıza göre değişebileceğini unutmayın.
Bu benzersiz sınıf adı, Button.module.css
tanımladığınız stillerin yalnızca bu düğmeye uygulanmasını ve uygulamanızdaki diğer öğeleri etkilememesini sağlar. Ayrıca, karma sınıf adını açıkça hedeflemediği sürece başka hiçbir stilin bu düğmeyi etkilememesini de sağlar. Stillerin bu şekilde kapsüllenmesi CSS Modüllerinin ana faydalarından biridir.
CSS'yi kullanmanın bir diğer popüler yolu, styled-components veya duygu gibi JS'de CSS kitaplıklarını kullanmaktır. Bu kitaplıklar, CSS'nizi doğrudan JavaScript'inizin içine yazmanıza olanak tanır; bunun birçok avantajı vardır:
Styled-component'leri bir React uygulamasında nasıl kullanabileceğinize dair bir örnek:
import React from 'react'; import styled from 'styled-components'; const Button = styled.button` color: white; background-color: ${(props) => props.primary ? 'blue' : 'gray'}; `; const App = () => { return ( <div> <Button primary>Primary Button</Button> <Button>Secondary Button</Button> </div> ); }; export default App;
Bu örnekte Button
bileşeni, primary
özelliğine göre değişen dinamik stillere sahiptir.
CSS Modüllerini veya benzerlerini destekleyen bir JavaScript çerçevesiyle çalışmıyorsanız, BEM (Blok, Öğe, Değiştirici) gibi adlandırma yöntemlerini kullanarak CSS'nizi yine de etkili bir şekilde yönetebilirsiniz.
BEM, "Blok Öğe Değiştirici" anlamına gelir ve CSS'de yeniden kullanılabilir bileşenler ve kod paylaşımı oluşturmanıza yardımcı olan bir metodolojidir. BEM'i kullanarak CSS'nizi şu şekilde yapılandırabilirsiniz:
/* Block */ .top-menu { } /* Element */ .top-menu__item { } /* Modifier */ .top-menu__item_active { }
BEM'de, 'Blok' kendi başına anlamlı olan bağımsız varlıktır, 'Element', Bloğun bağımsız bir anlamı olmayan ve Bloğuna anlamsal olarak bağlı olan bir parçasıdır ve 'Değiştirici', üzerindeki bir bayraktır. görünümü veya davranışı değiştirmek için kullanılan bir Blok veya Öğe.
BEM gibi tutarlı bir metodoloji kullanmak, özellikle büyük projelerde CSS'nizin anlaşılmasını ve bakımını kolaylaştırabilir.
Daha büyük projelerde CSS'yi yönetmenin, CSS Modülleri ve JS'deki CSS kitaplıklarından BEM gibi adlandırma metodolojilerine kadar çeşitli yolları vardır. Önemli olan ekibinize ve projenize uygun bir yaklaşım bulmak ve bunu tutarlı bir şekilde uygulamaktır. CSS yazmanın, verimli ve performanslı kod yazmanın yanı sıra anlaşılır ve bakımı yapılabilir kod yazmakla da ilgili olduğunu unutmayın.
Mutlu kodlama!