-
Posts
25 -
Joined
-
Last visited
Content Type
Profiles
Blogs
Events
Everything posted by Doğuhan ELMA
-
1. Scrollbar Anatomisi ve Tarayıcı Davranışı a) Scrollbar Bileşenleri ┌─────────────────────────┐ │ ▲ (up button) │ ← Scrollbar button ├─────────────────────────┤ │ │ ← Track (kanal) │ ████ │ ← Thumb (kaydırıcı) │ │ │ │ ├─────────────────────────┤ │ ▼ (down button) │ └─────────────────────────┘ Bileşenler: Track (Kanal): Scrollbar'ın arka plan alanı Thumb (Kaydırıcı): Hareket eden kısım Buttons: Ok butonları (bazı işletim sistemlerinde) Corner: İki scrollbar'ın kesiştiği köşe b) Scrollbar Türleri /* Klasik (Classic) Scrollbar */ /* - Her zaman görünür - Sabit genişlik (genellikle 15-17px) - Layout'u etkiler */ /* Overlay Scrollbar */ /* - İçerik üzerinde yüzer - Layout'u etkilemez - Kullanılmadığında kaybolur - macOS, mobil cihazlar */ 2. Scrollbar ve Layout İlişkisi a) Scrollbar'ın Layout'a Etkisi <div class="container"> <div class="content">İçerik</div> </div> /* Klasik Scrollbar Davranışı */ .container { width: 500px; height: 300px; overflow: auto; } /* Scrollbar YOKSA: - İçerik alanı: 500px genişlik Scrollbar VARSA (Windows, Linux): - İçerik alanı: ~483px genişlik (scrollbar ~17px) - Scrollbar içerik alanından yer kaplar Scrollbar VARSA (macOS overlay): - İçerik alanı: 500px genişlik - Scrollbar içerik üzerinde yüzer */ b) Scrollbar Width Tespiti /* Scrollbar genişliğini hesaba kat */ .container { width: 500px; padding-right: 20px; /* İçerik için padding */ } /* Scrollbar göründüğünde içerik kayması */ .container { overflow-y: scroll; /* Her zaman göster */ /* veya */ scrollbar-gutter: stable; /* Alan rezerve et */ } 3. Scrollbar ve Relative Birimlerin Hesaplanması a) Viewport Birimleri (vw, vh) /* KRITIK: Viewport birimleri scrollbar'ı DIKKATE ALMAZ */ body { margin: 0; } .full-width { width: 100vw; /* Viewport genişliği */ /* Scrollbar varsa yatay taşma oluşur! */ } /* Problem gösterimi: */ html { overflow-y: scroll; /* Dikey scrollbar var */ } .container { width: 100vw; /* ~1920px (scrollbar dahil) */ /* Ama gerçek alan: ~1903px (scrollbar hariç) */ /* Sonuç: Yatay scrollbar belirir! */ } Çözüm Stratejileri: /* Çözüm 1: 100% kullan (önerilen) */ .full-width { width: 100%; /* Mevcut alanın tamamı */ } /* Çözüm 2: dvw kullan (modern) */ .full-width { width: 100dvw; /* Dynamic viewport width */ /* Scrollbar'ı dikkate alır */ } /* Çözüm 3: scrollbar-gutter */ html { overflow-y: scroll; scrollbar-gutter: stable; } .full-width { width: 100vw; /* scrollbar-gutter alanı rezerve ettiği için sorun yok */ } /* Çözüm 4: calc ile manuel düzeltme */ .full-width { width: calc(100vw - 20px); } b) Percentage (%) Birimleri /* Parent container'a göre hesaplama */ .parent { width: 500px; height: 300px; overflow: auto; } .child { width: 100%; /* Scrollbar YOKSA: 500px Scrollbar VARSA (klasik): ~483px Scrollbar VARSA (overlay): 500px */ } /* Yüzde hesaplaması her zaman CONTENT BOX üzerinden */ .parent { width: 500px; padding: 20px; overflow-y: scroll; /* Scrollbar: 17px */ box-sizing: border-box; } .child { width: 100%; /* 500px (total) - 40px (padding) - 17px (scrollbar) = 443px */ } c) Container Query Birimleri (cqw, cqh) .container { container-type: inline-size; width: 500px; overflow-y: auto; } .child { width: 50cqw; /* Container'ın genişliğinin %50'si Scrollbar varsa, scrollbar hariç alan üzerinden */ font-size: 5cqw; } d) ch ve em Birimleri /* ch ve em scrollbar'dan BAĞIMSIZDIR */ .text { max-width: 65ch; /* 65 karakter genişliği */ /* Scrollbar olup olmaması etkilemez */ } .spacing { padding: 1em; /* Font size'a göre */ /* Scrollbar etkisi yok */ } 4. Scrollbar'ı Etkileyen CSS Özellikleri a) overflow Ailesi /* overflow - temel kontrol */ .element { overflow: visible; /* Varsayılan - taşma görünür */ overflow: hidden; /* Taşma gizli - scrollbar yok */ overflow: scroll; /* Her zaman scrollbar */ overflow: auto; /* Gerektiğinde scrollbar */ overflow: clip; /* Taşma kesilir, scroll yok */ } /* Eksen bazlı kontrol */ .element { overflow-x: auto; /* Yatay scroll */ overflow-y: scroll; /* Dikey scroll */ } /* Modern: overflow inline/block */ .element { overflow-inline: auto; /* Yazı yönü bazlı */ overflow-block: scroll; /* Block yönü bazlı */ } /* overflow-anchor - scroll pozisyon kontrolü */ .chat-container { overflow-anchor: auto; /* DOM değişikliklerinde pozisyonu koru */ } b) scrollbar-gutter (Modern) /* Scrollbar için alan rezerve et */ .container { overflow-y: auto; scrollbar-gutter: auto; /* Varsayılan */ } /* Her zaman alan rezerve et */ .stable-layout { overflow-y: auto; scrollbar-gutter: stable; /* Scrollbar olmasa bile alan ayrılır Layout shift'i önler */ } /* İki taraflı (simetrik) */ .centered-content { overflow-y: auto; scrollbar-gutter: stable both-edges; /* Sağ ve solda simetrik alan */ } Kullanım Senaryosu: /* Modal açıldığında body scrollbar kaybolur */ body { overflow: hidden; /* Modal açık */ } /* Problem: Layout kayar (scrollbar alanı kaybolur) */ /* Çözüm: */ body { overflow-y: auto; scrollbar-gutter: stable; /* Scrollbar kaybolsa bile alan rezerve kalır */ } d) scrollbar-color (Firefox) /* Firefox için scrollbar renklendirme */ .custom-scrollbar { scrollbar-color: #888 #f1f1f1; /* İlk değer: thumb, İkinci değer: track */ } /* Temaya göre */ .dark-theme { scrollbar-color: #555 #222; } .light-theme { scrollbar-color: #ccc #fff; } /* Transparent */ .overlay-style { scrollbar-color: rgba(0, 0, 0, 0.3) transparent; } e) ::-webkit-scrollbar (Webkit/Blink) /* Webkit tabanlı tarayıcılar için özelleştirme */ /* Scrollbar genişliği */ .container::-webkit-scrollbar { width: 12px; /* Dikey scrollbar */ height: 12px; /* Yatay scrollbar */ } /* Track (kanal) */ .container::-webkit-scrollbar-track { background: #f1f1f1; border-radius: 10px; } /* Thumb (kaydırıcı) */ .container::-webkit-scrollbar-thumb { background: #888; border-radius: 10px; border: 2px solid #f1f1f1; /* Track rengiyle padding efekti */ } /* Hover durumu */ .container::-webkit-scrollbar-thumb:hover { background: #555; } /* Active durumu */ .container::-webkit-scrollbar-thumb:active { background: #333; } /* Corner (köşe) */ .container::-webkit-scrollbar-corner { background: #f1f1f1; } /* Buttons */ .container::-webkit-scrollbar-button { display: none; /* Ok butonlarını gizle */ } Detaylı Özelleştirme: /* Minimal modern scrollbar */ .modern-scroll { scrollbar-width: thin; scrollbar-color: rgba(0, 0, 0, 0.2) transparent; } .modern-scroll::-webkit-scrollbar { width: 8px; } .modern-scroll::-webkit-scrollbar-track { background: transparent; } .modern-scroll::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.2); border-radius: 4px; } .modern-scroll::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.4); } /* macOS benzeri */ .macos-style { scrollbar-width: thin; } .macos-style::-webkit-scrollbar { width: 10px; } .macos-style::-webkit-scrollbar-track { background: transparent; } .macos-style::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.3); border-radius: 10px; border: 2px solid transparent; background-clip: padding-box; } .macos-style::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.5); background-clip: padding-box; } f) scroll-behavior /* Smooth scroll davranışı */ html { scroll-behavior: smooth; } /* Anchor linkler için */ a[href^="#"] { scroll-behavior: smooth; } /* Kullanıcı tercihine saygı */ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } } g) overscroll-behavior /* Scroll sınırlarında davranış */ .modal-content { overscroll-behavior: contain; /* Scroll sonunda parent'a geçmez */ } body { overscroll-behavior-y: none; /* Bounce/pull-to-refresh engellenmiş */ } /* Eksen bazlı */ .horizontal-scroller { overscroll-behavior-x: contain; overscroll-behavior-y: auto; } h) scroll-snap /* Snap scroll davranışı */ .gallery { scroll-snap-type: x mandatory; overflow-x: auto; } .gallery-item { scroll-snap-align: start; scroll-snap-stop: always; /* Her öğede dur */ } /* Dikey snap */ .fullpage-sections { scroll-snap-type: y proximity; overflow-y: auto; } .section { scroll-snap-align: center; min-height: 100vh; } 5. Scrollbar ve Modern Tasarım a) Minimal/Invisible Scrollbar Trendi /* Gizli ama fonksiyonel scrollbar */ .minimal-scroll { overflow: auto; scrollbar-width: none; /* Firefox */ } .minimal-scroll::-webkit-scrollbar { display: none; /* Webkit/Blink */ } /* Hover'da görünen scrollbar */ .hover-scrollbar { scrollbar-width: none; } .hover-scrollbar:hover { scrollbar-width: thin; } .hover-scrollbar::-webkit-scrollbar { width: 0; transition: width 0.3s; } .hover-scrollbar:hover::-webkit-scrollbar { width: 8px; } b) Custom Scrollbar Tasarımları 1. Minimal Modern: .minimal { scrollbar-width: thin; scrollbar-color: #e0e0e0 transparent; } .minimal::-webkit-scrollbar { width: 6px; } .minimal::-webkit-scrollbar-track { background: transparent; } .minimal::-webkit-scrollbar-thumb { background: #e0e0e0; border-radius: 3px; } 2. Branded/Colorful: .branded { scrollbar-width: auto; scrollbar-color: var(--brand-color) var(--bg-color); } .branded::-webkit-scrollbar { width: 12px; } .branded::-webkit-scrollbar-track { background: var(--bg-color); } .branded::-webkit-scrollbar-thumb { background: linear-gradient( 180deg, var(--brand-color-light), var(--brand-color-dark) ); border-radius: 6px; } 3. Animated/Interactive: .interactive::-webkit-scrollbar-thumb { background: #888; transition: background 0.2s, transform 0.2s; } .interactive::-webkit-scrollbar-thumb:hover { background: #555; transform: scaleX(1.2); } .interactive::-webkit-scrollbar-thumb:active { background: #333; } Responsive Scrollbar Stratejileri /* Desktop - normal scrollbar */ @media (min-width: 1024px) { .content { scrollbar-width: auto; } .content::-webkit-scrollbar { width: 12px; } } /* Tablet - ince scrollbar */ @media (max-width: 1023px) and (min-width: 768px) { .content { scrollbar-width: thin; } .content::-webkit-scrollbar { width: 8px; } } /* Mobile - gizli scrollbar */ @media (max-width: 767px) { .content { scrollbar-width: none; } .content::-webkit-scrollbar { display: none; } } /* Touch device tespiti */ @media (hover: none) and (pointer: coarse) { .content { scrollbar-width: none; } } Scrollbar ve Performans a) will-change ile Optimizasyon .smooth-scroll { overflow-y: auto; will-change: scroll-position; /* GPU hızlandırma aktif */ } /* Dikkat: Sürekli kullanma */ .scroll-container:hover { will-change: scroll-position; } .scroll-container { will-change: auto; /* Hover sonrası kapat */ } b) contain ile İzolasyon .scroll-section { overflow: auto; contain: layout style paint; /* Scroll bu element içinde kalır */ /* Tarayıcı optimize edebilir */ } b) Split Panel Layout .split-panel { display: grid; grid-template-columns: 300px 1fr; height: 100vh; } .sidebar { overflow-y: auto; scrollbar-width: thin; overscroll-behavior: contain; } .main-content { overflow-y: auto; scrollbar-gutter: stable; } c) Horizontal Scroll Gallery .gallery { display: flex; gap: 1rem; overflow-x: auto; scrollbar-width: thin; /* macOS momentum scroll */ -webkit-overflow-scrolling: touch; /* Snap points */ scroll-snap-type: x mandatory; scroll-padding: 1rem; } .gallery-item { scroll-snap-align: start; flex: 0 0 300px; } /* Fade edges efekti */ .gallery-wrapper { position: relative; } .gallery-wrapper::before, .gallery-wrapper::after { content: ''; position: absolute; top: 0; bottom: 20px; /* Scrollbar yüksekliği */ width: 50px; pointer-events: none; z-index: 1; } .gallery-wrapper::before { left: 0; background: linear-gradient(to right, white, transparent); } .gallery-wrapper::after { right: 0; background: linear-gradient(to left, white, transparent); } /* ÖZELLEŞTIR: Branded deneyim */ .app-container { scrollbar-color: var(--brand-primary) var(--bg-secondary); } /* ÖZELLEŞTIRME: Dark theme */ @media (prefers-color-scheme: dark) { .content { scrollbar-color: #444 #1a1a1a; } } /* VARSAYILAN BIRAK: Standard içerik */ article { overflow: auto; /* İşletim sistemi scrollbar'ı en iyi */ } Özet: Scrollbar ve Modern CSS Kritik Noktalar: Viewport Hesaplamaları: 100vw scrollbar genişliğini içerir, layout kaymasına neden olabilir scrollbar-gutter: Modern çözüm, scrollbar için alan rezerve eder Özelleştirme: Firefox (scrollbar-width, scrollbar-color) ve Webkit (::-webkit-scrollbar-*) farklı yaklaşımlar Accessibility: Scrollbar gizlerken scroll işlevselliğini koruyun Performance: will-change ve contain ile optimize edin Modern Tasarım: Minimal, hover-revealed, overlay scrollbar trendleri Scrollbar, layout sisteminin kritik ama sık göz ardı edilen bir parçasıdır. Modern CSS özellikleri (scrollbar-gutter, dvw, container queries) bu zorlukları ele almak için geliştirilmiştir.
-
Metin okunabilirliği, kullanıcıların metni ne kadar kolay okuyabildiği ve anladığıyla ilgilidir. Bu, tipografi, spacing, kontrast ve layout kararlarının birleşimidir. 1. Temel Okunabilirlik Faktörleri a) Satır Uzunluğu (Line Length / Measure) Optimal: 45-75 karakter (İngilizce için), 50-80 karakter (Türkçe için) /* Kötü - çok geniş satırlar */ .article { max-width: 100%; /* 120+ karakter - gözler satır sonunu bulamaz */ } /* İyi - optimal satır uzunluğu */ .article { max-width: 65ch; /* ch birimi: karakter genişliği */ } /* Responsive optimal uzunluk */ .article { max-width: clamp(45ch, 90%, 75ch); } CSS Özellikleri: max-width ile satır uzunluğu kontrolü ch birimi (karakter genişliği) - tipografik ölçüm clamp() ile esnek sınırlar b) Satır Yüksekliği (Line Height / Leading) Optimal: 1.4-1.8 arası (metin boyutuna göre değişir) /* Kötü - çok sıkışık */ .text-cramped { line-height: 1; /* Satırlar birbirine yapışır */ } /* Kötü - çok gevşek */ .text-loose { line-height: 2.5; /* Satırlar arasında kopukluk */ } /* İyi - dengeli */ .paragraph { line-height: 1.6; } /* Boyut bazlı ayarlama */ .heading { font-size: 3rem; line-height: 1.2; /* Büyük metinler daha az line-height */ } .body-text { font-size: 1rem; line-height: 1.6; /* Küçük metinler daha fazla */ } /* Modern: lh birimi ile */ .paragraph { line-height: 1.5; margin-block-end: 1lh; /* 1 satır yüksekliği kadar boşluk */ } CSS Özellikleri: line-height - birimsize (1.5) veya birimli (1.5rem) lh birimi - satır yüksekliğine göre spacing leading-trim (gelecek özellik) - tipografik hassasiyet c) Font Boyutu (Font Size) Optimal: 16px-18px body text için /* Kötü - sabit piksel */ body { font-size: 14px; /* Kullanıcı tercihleri göz ardı */ } /* İyi - göreceli birim */ body { font-size: 1rem; /* Tarayıcı ayarlarına saygı */ } /* Daha iyi - responsive */ body { font-size: clamp(1rem, 0.9rem + 0.5vw, 1.125rem); /* Küçük ekran: 16px, büyüdükçe 18px'e kadar */ } /* Hiyerarşi ile */ :root { --font-size-sm: 0.875rem; /* 14px */ --font-size-base: 1rem; /* 16px */ --font-size-lg: 1.125rem; /* 18px */ --font-size-xl: 1.25rem; /* 20px */ } .small-text { font-size: var(--font-size-sm); } .body-text { font-size: var(--font-size-base); } CSS Özellikleri: font-size - rem, em, clamp() font-size-adjust - farklı fontlar arasında tutarlılık 2. Tipografi ve Font Özellikleri a) Font Seçimi ve Okunabilirlik /* Sistem fontları - hızlı ve okunabilir */ body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; } /* Okuma için serif */ .article-content { font-family: Georgia, "Times New Roman", serif; font-size: 1.125rem; line-height: 1.7; } /* Kod için monospace */ code { font-family: "SF Mono", Monaco, "Cascadia Code", "Courier New", monospace; font-size: 0.9em; /* Parent'a göre biraz küçük */ } b) Font Weight (Kalınlık) /* Okunabilirlik için optimal ağırlıklar */ body { font-weight: 400; /* Normal - body text için */ } .heading { font-weight: 700; /* Bold - başlıklar için */ } .lead-text { font-weight: 500; /* Medium - vurgu için */ } /* Variable fonts ile hassas kontrol */ @supports (font-variation-settings: normal) { .text { font-variation-settings: "wght" 450; /* 400-500 arası hassas ayar */ } } /* İnce fontlar kontrast gerektirir */ .thin-text { font-weight: 300; font-size: 1.125rem; /* Daha büyük boyut */ color: #000; /* Daha yüksek kontrast */ } CSS Özellikleri: font-weight - 100-900 arası değerler font-variation-settings - variable fonts için c) Font Optical Sizing /* Farklı boyutlarda optimal form */ .text { font-optical-sizing: auto; /* Font boyuta göre otomatik optimize olur */ } /* Büyük başlıklarda display variant */ .hero-title { font-size: 4rem; font-optical-sizing: auto; /* Büyük boyut için optimize edilmiş formlar */ } 3. Karakter ve Kelime Spacing a) Letter Spacing (Karakter Aralığı) /* Genellikle varsayılan en iyisidir */ .body-text { letter-spacing: normal; } /* Büyük başlıklarda sıkıştırma */ .display-heading { font-size: 5rem; letter-spacing: -0.02em; /* Negatif tracking */ } /* Küçük büyük harfler için açma */ .small-caps { font-variant: small-caps; letter-spacing: 0.05em; } .uppercase-label { text-transform: uppercase; letter-spacing: 0.1em; font-size: 0.875rem; } Kural: Büyük fontlar → negatif letter-spacing Küçük fontlar / ALL CAPS → pozitif letter-spacing b) Word Spacing /* Nadiren değiştirilmeli */ .text { word-spacing: normal; } /* Çok dar yazılarda */ .narrow-column { max-width: 35ch; word-spacing: 0.1em; /* Biraz daha fazla boşluk */ } 4. Renk ve Kontrast a) Renk Kontrastı (WCAG Standartları) WCAG AA: Minimum 4.5:1 (normal metin), 3:1 (büyük metin) WCAG AAA: Minimum 7:1 (normal metin), 4.5:1 (büyük metin) /* Kötü kontrast - okunaksız */ .low-contrast { color: #999; background: #fff; /* Kontrast: 2.8:1 - yetersiz */ } /* İyi kontrast */ .good-contrast { color: #333; background: #fff; /* Kontrast: 12.6:1 - mükemmel */ } /* Karanlık mod için */ @media (prefers-color-scheme: dark) { body { color: #e0e0e0; background: #121212; /* Kontrast: 13.9:1 */ } } /* Modern: color-contrast() fonksiyonu (gelecek) */ .text { color: color-contrast( var(--background) vs #000, #333, #666 ); /* En iyi kontrast otomatik seçilir */ } CSS Özellikleri: color ve background-color color-contrast() (gelecek özellik) prefers-contrast media query b) Alt Metin Renkleri /* Link renkleri - yeterli kontrast */ a { color: #0066cc; /* Ana metinden ayırt edilebilir */ } a:visited { color: #551a8b; /* Ziyaret edilmiş linkler farklı */ } /* Disabled metin */ .disabled-text { color: #767676; /* Minimum 4.5:1 kontrast korunmalı */ } /* Placeholder metinler */ input::placeholder { color: #757575; opacity: 1; /* Varsayılan opacity kaldırılmalı */ } 5. Hizalama ve Metin Düzeni a) Text Alignment /* Batı dilleri için soldan hizalama en okunabilir */ .paragraph { text-align: start; /* Dil yönünü otomatik dikkate alır */ } /* Justify - dikkatli kullanılmalı */ .article { text-align: justify; hyphens: auto; /* Kelime bölme ile birlikte */ /* Yoksa kelimeler arası büyük boşluklar */ } /* Ortalama - sadece kısa metinler için */ .heading { text-align: center; max-width: 30ch; /* Çok uzun satırlar ortalanmamalı */ } Modern Özellikler: /* Mantıksal hizalama */ .text { text-align: start; /* left yerine */ text-align: end; /* right yerine */ /* RTL dillerde otomatik ters çevrilir */ } b) Hyphens (Kelime Bölme) /* Dar sütunlarda yararlı */ .narrow-column { max-width: 40ch; hyphens: auto; /* Kelimeler uygun şekilde bölünür */ } /* Türkçe için */ .turkish-text { hyphens: auto; lang: tr; /* HTML'de lang="tr" olmalı */ } /* Uzun kelimelerin kontrolü */ .text { overflow-wrap: break-word; word-break: break-word; hyphens: auto; } c) Text Wrapping /* Uzun URL'ler ve kelimeler */ .url-text { word-break: break-all; /* Her karakterden bölebilir */ /* veya */ overflow-wrap: anywhere; /* Boşluk yoksa böler */ } /* Başlıklar - widows/orphans önleme */ .heading { text-wrap: balance; /* Satırlar dengeli uzunlukta */ } /* Paragraflar */ .paragraph { text-wrap: pretty; /* Orphan'ları önler */ } 6. Paragraph Spacing a) Paragraph Margins /* Paragraflar arası boşluk */ .paragraph { margin-block-end: 1em; /* Font boyutuna göre */ /* veya */ margin-block-end: 1lh; /* Satır yüksekliğine göre */ } /* İlk paragraf girintisi (opsiyonel) */ .paragraph + .paragraph { text-indent: 1.5em; margin-block-start: 0; } /* Responsive spacing */ .article { --paragraph-spacing: clamp(1rem, 0.5rem + 1vw, 1.5rem); } .paragraph { margin-block-end: var(--paragraph-spacing); } b) Drop Caps (Baş Harf Süsleme) .paragraph::first-letter { initial-letter: 3; /* 3 satır yüksekliğinde */ font-weight: 700; margin-inline-end: 0.5em; color: var(--accent-color); } 7. Başlık Hiyerarşisi ve Okunabilirlik /* Type scale - harmonik oran */ :root { --ratio: 1.25; /* Major third */ --font-size-base: 1rem; --font-size-h6: var(--font-size-base); --font-size-h5: calc(var(--font-size-h6) * var(--ratio)); --font-size-h4: calc(var(--font-size-h5) * var(--ratio)); --font-size-h3: calc(var(--font-size-h4) * var(--ratio)); --font-size-h2: calc(var(--font-size-h3) * var(--ratio)); --font-size-h1: calc(var(--font-size-h2) * var(--ratio)); } h1, h2, h3, h4, h5, h6 { line-height: 1.2; font-weight: 700; margin-block-end: 0.5em; } h1 { font-size: var(--font-size-h1); } h2 { font-size: var(--font-size-h2); } h3 { font-size: var(--font-size-h3); } /* ... */ /* Başlıktan sonra paragraf spacing */ h1 + p, h2 + p, h3 + p { margin-block-start: 0.75em; } 8. Accessibility ve Okunabilirlik a) Kullanıcı Tercihleri /* Reduced motion */ @media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; } } /* Contrast tercihi */ @media (prefers-contrast: high) { body { color: #000; background: #fff; } } /* Font boyutu artırma desteği */ html { font-size: 100%; /* Tarayıcı varsayılanına saygı */ } body { font-size: 1rem; /* Göreceli birim kullan */ } b) Focus States /* Klavye navigasyonu için görünür focus */ :focus-visible { outline: 3px solid var(--focus-color); outline-offset: 2px; } /* Link focus */ a:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; text-decoration: none; } 9. Responsive Typography a) Fluid Typography /* Viewport bazlı scaling */ body { font-size: clamp(1rem, 0.875rem + 0.5vw, 1.25rem); /* Küçük: 16px, Orta: ~18px, Büyük: 20px */ } h1 { font-size: clamp(2rem, 1.5rem + 2vw, 4rem); line-height: 1.1; } /* Container query ile */ @container (min-width: 600px) { .card-title { font-size: 1.5rem; } } b) Responsive Line Length .article { /* Ekran genişliğine göre ama maksimum karakter */ width: min(90%, 70ch); margin-inline: auto; } /* Container içinde */ .sidebar-article { max-width: 55ch; /* Dar alanlarda daha kısa satır */ } 10. Advanced CSS Features a) CSS Subgrid ile Hizalama .article-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; } .article-card { display: grid; grid-template-rows: subgrid; grid-row: span 3; } /* Tüm başlıklar ve metinler hizalı */ b) Text Decoration /* Okunabilir link altı çizgileri */ a { text-decoration: underline; text-decoration-thickness: 0.1em; text-decoration-color: var(--link-color); text-underline-offset: 0.2em; } a:hover { text-decoration-thickness: 0.15em; } 11. Okunabilirlik Kontrol Listesi Optimal Ayarlar: .readable-text { /* Font */ font-family: system-ui, sans-serif; font-size: clamp(1rem, 0.9rem + 0.5vw, 1.125rem); font-weight: 400; /* Spacing */ line-height: 1.6; letter-spacing: normal; max-width: 70ch; /* Layout */ margin-block-end: 1lh; text-align: start; text-wrap: pretty; /* Renk */ color: #333; background: #fff; /* Responsive */ hyphens: auto; overflow-wrap: break-word; } Özet: Metin Okunabilirliği Prensipleri Satır Uzunluğu: 45-75 karakter (max-width: 65ch) Satır Yüksekliği: 1.5-1.8 arası (line-height) Font Boyutu: Minimum 16px (font-size: 1rem) Kontrast: Minimum 4.5:1 (WCAG AA) Hizalama: Sol hizalama en okunabilir Spacing: Yeterli paragraph ve heading spacing Responsive: Fluid typography ve optimal line length Accessibility: Kullanıcı tercihlerine saygı Modern CSS, bu okunabilirlik faktörlerini kontrol etmek için güçlü araçlar sunar: clamp(), ch birimi, lh birimi, mantıksal özellikler, text-wrap, container queries ve daha fazlası. Bu özellikleri doğru kullanmak, her ekran boyutunda ve her kullanıcı için optimal okuma deneyimi sağlar.
-
lh birimi, CSS'de line-height (satır yüksekliği) değerine göre hesaplanan görece yeni bir uzunluk birimidir. Bir elementin hesaplanmış satır yüksekliğini temsil eder. Temel Tanım 1lh, elementin kendi line-height değerine eşittir. Örneğin: .element { font-size: 16px; line-height: 1.5; /* 24px */ margin-bottom: 1lh; /* 24px olur */ } Nasıl Çalışır? lh birimi, kullanıldığı elementin hesaplanmış line-height değerini referans alır: .card { font-size: 18px; line-height: 1.6; /* 28.8px */ padding-top: 0.5lh; /* 14.4px */ margin-bottom: 2lh; /* 57.6px */ gap: 1lh; /* 28.8px */ } Miras ve Hesaplama lh, line-height'ın nihai hesaplanmış değerini kullanır: body { font-size: 16px; line-height: 1.5; /* 24px */ } .content { font-size: 20px; /* line-height miras alınır: 1.5 × 20px = 30px */ margin-top: 1lh; /* 30px olur */ } Modern Tasarımdaki Yeri 1. Dikey Ritim (Vertical Rhythm) lh birimi, tipografik ızgara sistemleri için mükemmeldir: .article { font-size: 18px; line-height: 1.6; /* Tüm boşluklar satır yüksekliğinin katları */ h2 { margin-top: 2lh; margin-bottom: 1lh; } p { margin-bottom: 1lh; } ul { margin: 1lh 0; padding-left: 2lh; } } Bu yaklaşım, metinler arasında tutarlı ve harmonik boşluklar oluşturur. 2. Dinamik Ölçeklendirme Font boyutu değiştiğinde, lh bazlı boşluklar otomatik uyum sağlar: .text-block { font-size: clamp(16px, 4vw, 24px); line-height: 1.5; padding: 1lh; } /* Küçük ekranlarda: 16px × 1.5 = 24px padding */ /* Büyük ekranlarda: 24px × 1.5 = 36px padding */ 3. Responsive Tasarım Farklı ekran boyutlarında orantılı boşluklar: .content { font-size: 16px; line-height: 1.5; } @media (min-width: 768px) { .content { font-size: 18px; /* line-height: 1.5 korunur ama değer 27px olur */ /* Tüm lh bazlı değerler otomatik ölçeklenir */ } } 4. Component-Based Tasarım Her komponentin kendi tipografik sistemini korur: .card { font-size: 14px; line-height: 1.4; padding: 1lh; gap: 0.5lh; } .hero { font-size: 32px; line-height: 1.2; padding: 1lh; /* card'dan farklı ama orantılı */ } Pratik Kullanım Örnekleri Örnek 1: Blog Yazısı Düzeni .blog-post { font-size: 18px; line-height: 1.6; max-width: 65ch; } .blog-post h1 { font-size: 2em; line-height: 1.2; margin-bottom: 0.5lh; } .blog-post h2 { margin-top: 2lh; margin-bottom: 1lh; } .blog-post p { margin-bottom: 1lh; } .blog-post blockquote { margin: 1.5lh 0; padding-left: 1lh; border-left: 0.2lh solid #ccc; } Örnek 2: Grid Layout .grid { display: grid; gap: 1lh; /* Satır yüksekliği kadar boşluk */ line-height: 1.5; } .grid-item { padding: 1lh; } Örnek 3: Form Elemanları .form-group { font-size: 16px; line-height: 1.5; margin-bottom: 1lh; } .form-label { display: block; margin-bottom: 0.5lh; } .form-input { height: 2lh; /* İki satır yüksekliğinde */ padding: 0 0.5lh; } Em ve Rem ile Karşılaştırma .comparison { font-size: 20px; line-height: 1.6; /* 32px */ margin-bottom: 1em; /* 20px - font-size'a göre */ padding: 1rem; /* 16px - root font-size'a göre */ gap: 1lh; /* 32px - line-height'a göre */ } em: Font boyutuna bağlı rem: Root font boyutuna bağlı lh: Satır yüksekliğine bağlı Tarayıcı Desteği lh birimi modern tarayıcılarda desteklenir: Chrome 109+ Firefox 120+ Safari 16.4+ Edge 109+ Eski tarayıcılar için fallback kullanabilirsiniz: .element { margin-bottom: 24px; /* fallback */ margin-bottom: 1lh; } Avantajları Tutarlılık: Dikey boşluklar her zaman tipografik ızgaraya uygun Bakım kolaylığı: line-height değiştiğinde tüm boşluklar otomatik uyum sağlar Okunabilirlik: Metinler arası boşluklar doğal ve orantılı Esneklik: Farklı font boyutlarında otomatik ölçeklenir Ne Zaman Kullanmalı? lh birimini şu durumlarda tercih edin: Dikey boşlukları tipografik ızgaraya bağlamak istediğinizde Satırlar arası boşluklarla uyumlu margin/padding değerleri oluşturmak istediğinizde Font boyutu değiştiğinde orantılı ölçeklenen boşluklar gerektiğinde Component tabanlı, tutarlı tipografi sistemi kurarken lh birimi, modern CSS'in getirdiği tipografi odaklı yaklaşımın güzel bir örneğidir ve özellikle içerik ağırlıklı sitelerde dikey ritmi korumak için oldukça değerlidir.
-
- css
- css lh units
-
(and 1 more)
Tagged with:
-
CSS'teki line-height (satır yüksekliği) özelliğinin değeri, modern web tasarımında metin okunabilirliğini ve dikey ritmi sağlamak için kritik öneme sahiptir. CSS'in en kritik tipografi özelliklerinden biridir. Duyarlı (responsive) tasarımlarda okunabilirliği artırmak temel hedeftir. line-height temel olarak, bir metin satırının yukarısındaki ve aşağısındaki görünmez boşluğu (leading) belirler. Bu boşluk, satırın kendisinin yüksekliğini oluşturur ve metin boyutuyla (font-size) ilişkilidir. Modern CSS değer birimi, Unitless (birimsiz)'dir. Adaptif ve Ölçeklenebilir bir çözüm sunar. Bu, dikey ritmin ve okuma konforunun tüm cihaz ve boyutlarda korunmasını sağlar. Değer türü Örnek Kabul edilir mi? Açıklama Unitless (birimsiz) 1.5 ✔ Oransal, en önerilen yöntem Pixel 20px ✔ Sabit uzunluk Em 1.2em ✔ Yazı boyutuna bağlı Rem 1.4rem ✔ Root font-size’a bağlı Yüzde 120% ✔ Oran olarak Normal normal ✔ Tarayıcı varsayılanı Viewport 3vh ✘ Geçersiz fr 1fr ✘ Grid’e özeldir Temel Konsept line-height, bir satırın toplam yüksekliğini belirler (font yüksekliği + üst/alt boşluk): ┌─────────────────────┐ ← Line box top │ ↑ Leading │ │ ┌─────────┐ │ │ │ Text │ │ ← Font size │ └─────────┘ │ │ ↓ Leading │ └─────────────────────┘ ← Line box bottom Leading = (line-height - font-size) / 2 Değer Tipleri ve Davranışları 1. Unitless (Oran) - ✅ EN İYİ UYGULAMA p { font-size: 16px; line-height: 1.5; /* Oransal - font-size'ın 1.5 katı */ /* = 16px * 1.5 = 24px */ } Miras davranışı: .parent { font-size: 16px; line-height: 1.5; /* ORAN miras alınır */ } .child { font-size: 32px; /* line-height: 1.5 ORANI miras alır */ /* = 32px * 1.5 = 48px ✅ DOĞRU */ } 2. Piksel (px) - ❌ KÖTÜ UYGULAMA p { font-size: 16px; line-height: 24px; /* Sabit değer */ } Miras davranışı: .parent { font-size: 16px; line-height: 24px; /* HESAPLANMIŞ DEĞER miras alınır */ } .child { font-size: 32px; /* line-height: 24px sabit değer miras alır */ /* Metin üst üste biner! ❌ SORUNLU */ } 3. Yüzde (%) - ❌ YANILTICI p { font-size: 16px; line-height: 150%; /* = 24px olarak HESAPLANIR */ } Miras davranışı: .parent { font-size: 16px; line-height: 150%; /* Parent'ta 24px olarak hesaplanır */ } .child { font-size: 32px; /* line-height: 24px (hesaplanmış değer) miras alır */ /* Yine sorunlu! ❌ */ } 4. Em Birimi - ❌ KARMAŞIK p { font-size: 16px; line-height: 1.5em; /* = 16px * 1.5 = 24px olarak HESAPLANIR */ } Miras davranışı: .parent { font-size: 16px; line-height: 1.5em; /* = 24px hesaplanır */ } .child { font-size: 32px; /* line-height: 24px miras alır ❌ */ } 5. Rem Birimi - ⚠️ ÖZELLİKLE KULLAN :root { font-size: 16px; } p { font-size: 1rem; /* 16px */ line-height: 1.5rem; /* = 24px sabit */ } h1 { font-size: 2rem; /* 32px */ /* Eğer line-height belirtilmezse, parent'tan miras alır */ /* 24px alırsa sorunlu olur */ } Detaylı Karşılaştırma /* Test senaryosu */ .container { font-size: 16px; } /* Senaryo 1: Unitless ✅ */ .container-unitless { line-height: 1.5; /* Oran */ } .container-unitless .small { font-size: 12px; /* line-height = 12px * 1.5 = 18px ✅ */ } .container-unitless .large { font-size: 32px; /* line-height = 32px * 1.5 = 48px ✅ */ } /* Senaryo 2: Piksel ❌ */ .container-px { line-height: 24px; /* Sabit */ } .container-px .small { font-size: 12px; /* line-height = 24px (geniş boşluk) ⚠️ */ } .container-px .large { font-size: 32px; /* line-height = 24px (metin üst üste biner!) ❌ */ } /* Senaryo 3: Yüzde ❌ */ .container-percent { line-height: 150%; /* 16px * 150% = 24px hesaplanır */ } .container-percent .large { font-size: 32px; /* line-height = 24px miras alır ❌ */ } /* Senaryo 4: Em ❌ */ .container-em { line-height: 1.5em; /* 16px * 1.5 = 24px hesaplanır */ } .container-em .large { font-size: 32px; /* line-height = 24px miras alır ❌ */ } Line-height Değeri Nasıl Hesaplanır? İdeal Değerler: Kısa Satırlar (Başlıklar, Navigasyon): Daha küçük değerler (örneğin, 1.2 - 1.4) kullanılabilir. Çünkü satır uzunluğu kısaldıkça gözün bir sonraki satıra geçme zorluğu azalır. Uzun Satırlar (Gövde Metni/Paragraf): Okunabilirliği artırmak için daha büyük değerler (örneğin, 1.5 - 1.6) kullanılır. Satır uzadıkça, okuyucunun kaybolmadan bir sonraki satırın başına kolayca dönmesi için daha fazla boşluğa ihtiyacı vardır. Font Tasarımı: Her yazı tipi, büyük ve küçük harflerinin boyutunu ve tasarımını (x-yüksekliği) farklı şekilde yönetir. Kullanılan fonta göre line-height değeri değişebilir. X-yüksekliği büyük olan fontlar daha kolay okunur. X-yüksekliği azaldıkça line-height değeri artar. Leading (Satır Aralığı) .text { font-size: 16px; line-height: 1.5; /* = 24px */ } /* Leading hesaplama: Leading = line-height - font-size Leading = 24px - 16px = 8px Üst boşluk = 8px / 2 = 4px Alt boşluk = 8px / 2 = 4px */ Normal Değeri p { line-height: normal; /* Tarayıcı varsayılanı */ /* Çoğu tarayıcıda ~1.2 */ /* Font'a göre değişebilir */ } Dikkat: normal değeri font'a bağlı olarak değişir, tahmin edilemez. Daima açık değer belirt. Tipografi için İdeal Değerler Genel Kurallar /* Body metni - Paragraflar */ body { line-height: 1.6; /* Optimal okunabilirlik */ /* 1.5 - 1.8 arası genelde iyi */ } /* Başlıklar */ h1, h2, h3, h4, h5, h6 { line-height: 1.2; /* Sıkı - başlıklar tek/iki satırlık */ /* 1.1 - 1.3 arası */ } /* Küçük metinler */ .small-text { font-size: 0.875rem; /* 14px */ line-height: 1.4; } /* Büyük display metinler */ .display { font-size: 4rem; line-height: 1; /* Çok sıkı veya 1.1 */ } /* Kod blokları */ code, pre { line-height: 1.6; /* Kod okunabilirliği için */ } /* Butonlar - Tek satır */ .button { line-height: 1; /* Dikey ortalama için */ padding: 0.75em 1.5em; /* Em ile oransal padding */ } /* Liste elemanları */ li { line-height: 1.8; /* Listeler için daha geniş */ } /* İnce/uzun yazı kolonları */ .narrow-column { max-width: 40ch; line-height: 1.8; /* Dar kolonlarda daha geniş */ } /* Geniş yazı kolonları */ .wide-column { max-width: 80ch; line-height: 1.5; /* Geniş kolonlarda daha sıkı */ } Bilimsel Temeller Okunabilirlik araştırmaları: Optimal: 45-75 karakter genişliğinde satırlar için line-height: 1.5-1.6 Dar kolonlar (<45 karakter): line-height: 1.7-1.8 Geniş kolonlar (>75 karakter): line-height: 1.4-1.5 Başlıklar: line-height: 1.1-1.3 lh Birimi (Yeni) /* Line-height'a göre oransal birim */ .text-box { line-height: 1.5; /* = 24px (16px font için) */ /* Padding line-height'ın yarısı */ padding-block: 0.5lh; /* = 12px */ /* Margin line-height kadar */ margin-bottom: 1lh; /* = 24px */ } /* Dikey ritim için mükemmel */ .rhythm-element { line-height: 1.6; margin-bottom: 1lh; /* Her zaman line-height kadar */ }
-
- css
- css line-heght
-
(and 2 more)
Tagged with:
-
CSS'te bazı özellikler birim gerektirmeyen saf sayı değerleri kabul eder. Bu "unitless numbers" kavramı, CSS'in temel mekaniklerinden biridir. Özellik Unitless kabul eder mi? Örnek Açıklama line-height ✔ line-height: 1.4; Font yüksekliği ile çarpılan oran. z-index ✔ z-index: 10; Katman sırası. opacity ✔ opacity: 0.6; 0–1 arasında saydamlık oranı. font-weight ✔ font-weight: 700; 100–900 arası kalınlık. flex-grow ✔ flex-grow: 2; Elemanın büyüme oranı. flex-shrink ✔ flex-shrink: 0; Elemanın küçülme oranı. flex (kısa kullanım) ✔ (ilk 2 değer) flex: 1 0 auto; İlk iki değer (grow/shrink) unitless’tır. animation-iteration-count ✔ animation-iteration-count: 3; Tekrar sayısı. grid-row / grid-column (span) ✔ grid-column: span 3; Kaç hücre genişleyeceğini belirleyen unitless sayı. order ✔ order: 2; Flex/Grid sıralaması için saf sayı. line-clamp ✔ line-clamp: 3; Kaç satır gösterileceği. orphans ✔ orphans: 2; Sayfa bölünmesinde minimum satır. widows ✔ widows: 2; Sayfa bölünmesinde maksimum satır. Unitless Numbers Kullanan CSS Özellikleri 1. line-height (En Önemli Kullanım) /* ❌ Birimli - KÖTÜ UYGULAMA */ p { font-size: 16px; line-height: 24px; /* Sabit değer */ } /* ❌ Yüzde - Şaşırtıcı davranış */ p { font-size: 16px; line-height: 150%; /* = 24px olarak hesaplanır ve KALSALAŞıR */ } /* ✅ Unitless - EN İYİ UYGULAMA */ p { font-size: 16px; line-height: 1.5; /* Font-size'ın 1.5 katı = 24px */ } Line-height'ta Unitless Neden Kritik? /* Miras davranışını görelim */ .parent { font-size: 16px; line-height: 24px; /* Sabit değer */ } .child { font-size: 32px; /* line-height: 24px kalır - SORUN! */ /* Metin üst üste biner */ } /* Yüzde ile */ .parent { font-size: 16px; line-height: 150%; /* = 24px hesaplanır ve bu değer miras alınır */ } .child { font-size: 32px; /* line-height: 24px (parent'tan miras) - SORUN! */ } /* ✅ Unitless ile - ÇÖZÜM */ .parent { font-size: 16px; line-height: 1.5; /* Oran miras alınır, değer değil */ } .child { font-size: 32px; /* line-height: 1.5 oranı miras alınır */ /* = 32px * 1.5 = 48px - DOĞRU! */ } Kural: line-height için DAIMA unitless kullan! Pratik Line-height Değerleri /* Genel kurallar */ body { line-height: 1.6; /* Paragraf metinleri için ideal */ } h1, h2, h3, h4, h5, h6 { line-height: 1.2; /* Başlıklar için sıkı */ } .small-text { line-height: 1.4; /* Küçük metinler için */ } .code { line-height: 1.6; /* Kod blokları için */ } .button { line-height: 1; /* Tek satır butonlar için */ } .loose-text { line-height: 1.8; /* Geniş satır aralığı */ } 2. opacity (Şeffaflık) .element { opacity: 0; /* Tamamen şeffaf */ opacity: 0.5; /* %50 şeffaf */ opacity: 1; /* Tamamen opak */ } /* ❌ Birim kullanılamaz */ opacity: 50%; /* Geçersiz (bazı tarayıcılar destekler ama standart değil) */ opacity: 0.5px; /* Geçersiz */ /* Pratik kullanım */ .disabled { opacity: 0.5; cursor: not-allowed; } .hover-effect { opacity: 1; transition: opacity 0.3s; } .hover-effect:hover { opacity: 0.8; } .fade-in { opacity: 0; animation: fadeIn 0.5s forwards; } @keyframes fadeIn { to { opacity: 1; } } 3. z-index (Katman Sırası) .element { position: relative; z-index: 10; /* Unitless integer */ } /* ❌ Birim kullanılamaz */ z-index: 10px; /* Geçersiz */ z-index: 1.5; /* Çalışır ama tam sayı olmalı */ 4. flex-grow, flex-shrink, flex-basis (flex'te 0 hariç) /* flex-grow - Unitless */ .item { flex-grow: 1; /* Boş alanı eşit paylaş */ flex-grow: 2; /* 2 kat daha fazla alan al */ } /* flex-shrink - Unitless */ .item { flex-shrink: 1; /* Normal küçülme */ flex-shrink: 0; /* Hiç küçülme */ } /* flex kısaltması */ .item { flex: 1; /* flex: 1 1 0 anlamına gelir */ /* grow shrink basis */ } /* Pratik flex kullanımı */ .container { display: flex; } .sidebar { flex: 0 0 250px; /* Büyümez, küçülmez, 250px sabit */ } .content { flex: 1; /* Kalan alanı kaplar */ } .priority-item { flex-grow: 2; /* Diğerlerinden 2x daha fazla büyür */ } 5. order (Flex/Grid Sırası) .flex-item { order: 0; /* Varsayılan */ order: 1; /* Sona gider */ order: -1; /* Başa gider */ } /* ❌ Birim kullanılamaz */ order: 1px; /* Geçersiz */ /* Responsive sıralama */ .mobile-first { order: -1; /* Mobilde en üstte */ } @media (min-width: 768px) { .mobile-first { order: 0; /* Desktop'ta normal sırada */ } } 6. font-weight (Yazı Kalınlığı) .element { font-weight: 400; /* Normal - unitless */ font-weight: 700; /* Bold - unitless */ } /* İsimli değerler de kullanılabilir */ font-weight: normal; /* = 400 */ font-weight: bold; /* = 700 */ font-weight: lighter; /* Parent'tan daha ince */ font-weight: bolder; /* Parent'tan daha kalın */ /* Variable fonts ile */ @font-face { font-family: 'Inter'; src: url('inter-variable.woff2'); font-weight: 100 900; /* Desteklenen aralık */ } .heading { font-weight: 650; /* Özel değer - variable font gerekir */ } 7. column-count (Çok Kolonlu Düzen) .article { column-count: 3; /* 3 kolon - unitless */ } /* ❌ Birim kullanılamaz */ column-count: 3px; /* Geçersiz */ /* Responsive kolonlar */ .masonry { column-count: 1; } @media (min-width: 768px) { .masonry { column-count: 2; } } @media (min-width: 1024px) { .masonry { column-count: 3; } } 8. Animation ve Transform'da Unitless /* animation-iteration-count */ .element { animation: spin 2s infinite; /* infinite = unitless */ animation-iteration-count: 3; /* 3 kez - unitless */ } /* ❌ Birim kullanılamaz */ animation-iteration-count: 3px; /* Geçersiz */ /* transform: scale() */ .element { transform: scale(1.5); /* 1.5 katı - unitless */ transform: scale(2); /* 2 katı */ transform: scale(0.5); /* Yarısı */ /* İki eksende farklı */ transform: scale(2, 1.5); /* X: 2x, Y: 1.5x */ } /* transform: rotate() için derece GEREKIR */ transform: rotate(45deg); /* ✅ Doğru */ transform: rotate(45); /* ❌ Geçersiz */ Unitless vs Birimli - Karşılaştırma Line-height Detaylı Karşılaştırma /* Senaryo 1: Sabit değer (px) */ .parent-px { font-size: 16px; line-height: 24px; } .child-px { font-size: 20px; /* line-height: 24px miras alınır */ /* 20px font için 24px satır yüksekliği = sıkışık */ } /* Senaryo 2: Yüzde */ .parent-percent { font-size: 16px; line-height: 150%; /* = 24px olarak HESAPLANIR */ } .child-percent { font-size: 20px; /* line-height: 24px (hesaplanmış değer) miras alınır */ /* Yine sorunlu! */ } /* Senaryo 3: Em birimi */ .parent-em { font-size: 16px; line-height: 1.5em; /* = 24px olarak HESAPLANIR */ } .child-em { font-size: 20px; /* line-height: 24px miras alınır */ /* Aynı sorun! */ } /* Senaryo 4: Unitless ✅ */ .parent-unitless { font-size: 16px; line-height: 1.5; /* ORAN miras alınır */ } .child-unitless { font-size: 20px; /* line-height: 1.5 ORANI miras alınır */ /* = 20px * 1.5 = 30px - DOĞRU! */ } Unitless Numbers Kullanırken Dikkat Edilmesi Gerekenler 1. Line-height ile Calc Kullanımı /* ⚠️ Dikkatli ol */ .element { font-size: 16px; line-height: calc(1.5 + 0.2); /* = 1.7 - Unitless kalır ✅ */ line-height: calc(1.5 * 16px); /* = 24px - Birimli olur ❌ */ } /* ✅ Doğru kullanım */ .element { --line-height-base: 1.5; --line-height-adjust: 0.2; line-height: calc(var(--line-height-base) + var(--line-height-adjust)); /* Sonuç unitless kalır */ } Özet Unitless numbers CSS'in önemli bir konsepti ve belirli özellikler için zorunlu veya önerilen kullanım: Zorunlu unitless: opacity (0-1) z-index (integer) flex-grow / flex-shrink order column-count font-weight (100-900) animation-iteration-count transform: scale() aspect-ratio Şiddetle önerilen unitless: line-height (miras davranışı için kritik) Anahtar avantaj: Özellikle line-height için unitless kullanım, miras mekanizmasının doğru çalışmasını sağlar ve responsive tasarımda beklenmedik sorunları önler. Modern web tasarımında unitless numbers, temiz, maintainable ve tahmin edilebilir kod yazmak için temel taşlardan biridir!
-
calc() fonksiyonu, CSS'te matematiksel hesaplamalar yapmamızı sağlayar. calc() CSS fonksiyonu, modern web tasarımında en çok duyarlı (responsive), esnek (flexible) ve hassas (precise) düzenler oluşturmak amacıyla kullanılır. Sabit birimler (px, pt, cm gibi) → viewport değişse bile değişmez. Örneğin calc(100px + 50px) her zaman 150px olur. Göreceli birimler (%, vw, vh, em, rem gibi) → viewport veya parent(mesela javascript ile) element boyutu değiştiğinde yeniden hesaplanır. Temel Sözdizimi .element { width: calc(100% - 50px); /* calc(değer operator değer) */ } Desteklenen operatörler: + (toplama) - (çıkarma) * (çarpma) / (bölme) Kritik Kurallar 1. Boşluk Kuralları /* ✅ DOĞRU */ width: calc(100% - 20px); width: calc(100% + 20px); /* ❌ YANLIŞ - toplama/çıkarmada boşluk ŞART */ width: calc(100%-20px); width: calc(100%+20px); /* ✅ DOĞRU - çarpma/bölmede boşluk opsiyonel */ width: calc(100% / 2); width: calc(100%/2); width: calc(2 * 50px); width: calc(2*50px); Neden? CSS parser'ı 100%-20px ifadesini tek bir identifier olarak görebilir. Boşluk, operatörü netleştirir. 2. Farklı Birimleri Karıştırma calc()'ın en güçlü özelliği farklı birimleri bir araya getirebilmesi: .element { /* Yüzde + piksel */ width: calc(100% - 40px); /* Viewport + rem */ height: calc(100vh - 3rem); /* Em + piksel */ padding: calc(2em + 10px); /* Viewport genişliği + px */ font-size: calc(16px + 1vw); /* Ch (karakter genişliği) + rem */ max-width: calc(60ch + 2rem); } 3. Bölme İşleminde Özel Durum /* ✅ DOĞRU - saf sayı ile bölme */ width: calc(100% / 3); width: calc(100px / 2); /* ❌ YANLIŞ - iki birimli değeri bölme */ width: calc(100% / 50%); /* Geçersiz */ width: calc(100px / 20px); /* Geçersiz */ /* ✅ DOĞRU - birimli / saf sayı */ width: calc(100% / 3); padding: calc(2rem / 1.5); Kural: Bölme işleminde bölen saf sayı olmalı, birim taşımamalı. 4. Çarpma İşleminde Özel Durum /* ✅ DOĞRU */ width: calc(50px * 2); width: calc(2 * 50px); width: calc(100% * 0.5); /* ❌ YANLIŞ - iki birimli değeri çarpma */ width: calc(50px * 20px); /* Geçersiz */ width: calc(100% * 50%); /* Geçersiz */ Kural: Çarpma işleminde en az bir değer saf sayı olmalı. Gerçek Dünya Kullanım Senaryoları 1. Layout ve Spacing /* Sidebar + Content Layout */ .layout { display: flex; } .sidebar { width: 250px; } .content { width: calc(100% - 250px); /* Kalan alanı doldurur */ } /* Grid ile daha iyi alternatif */ .layout-grid { display: grid; grid-template-columns: 250px calc(100% - 250px); /* veya daha iyi: */ grid-template-columns: 250px 1fr; /* flex yerine */ } /* Container padding hariç genişlik */ .container { width: 1200px; padding: 0 2rem; } .inner { /* Parent genişliği - (padding * 2) */ width: calc(100% - 4rem); max-width: calc(1200px - 4rem); } 2. Viewport Tabanlı Hesaplamalar /* Full-height minus header/footer */ .main-content { min-height: calc(100vh - 80px - 60px); /* viewport - header - footer */ } /* Full viewport with safe margins */ .hero { height: calc(100vh - 4rem); /* Mobile için güvenli alan */ } /* Dynamic viewport units (dvh) ile */ .modern-hero { height: calc(100dvh - 4rem); /* Mobil tarayıcı UI'ını dikkate alır */ } /* Sticky footer pattern */ body { min-height: 100vh; display: flex; flex-direction: column; } main { flex: 1; /* veya calc ile: */ min-height: calc(100vh - 80px); } 3. Responsive Typography /* Fluid typography - basit */ h1 { font-size: calc(1.5rem + 2vw); /* Base 1.5rem + viewport'a göre büyüme */ } /* Bounded fluid typography */ h1 { font-size: calc(1.5rem + 2vw); font-size: clamp(2rem, calc(1.5rem + 2vw), 4rem); /* Min 2rem, ideal calc(...), max 4rem */ } /* Line height calculation */ p { font-size: 1rem; line-height: calc(1em + 0.5rem); /* Em ile rem kombinasyonu - responsive line-height */ } Dinamik Spacing /* Ekran boyutuna göre artan boşluk */ .section { padding-block: calc(2rem + 5vh); /* Minimum 2rem + viewport'un %5'i */ padding-inline: calc(1rem + 3vw); /* Yanlarda responsive boşluk */ } /* Modular scale */ .heading-1 { font-size: calc(1rem * 2.5); } /* 40px */ .heading-2 { font-size: calc(1rem * 2); } /* 32px */ .heading-3 { font-size: calc(1rem * 1.5); } /* 24px */ .body { font-size: 1rem; } /* 16px */ .small { font-size: calc(1rem * 0.875); } /* 14px */ Position ve Transform /* Tam ortalama */ .centered { position: absolute; top: calc(50% - 50px); left: calc(50% - 100px); /* Daha iyi alternatif: transform */ top: 50%; left: 50%; transform: translate(-50%, -50%); } /* Offset positioning */ .tooltip { position: absolute; bottom: calc(100% + 10px); /* Element'in üstünde, 10px boşlukla */ left: calc(50% - 75px); width: 150px; } Custom Properties ile Kombinasyon :root { --header-height: 80px; --footer-height: 60px; --sidebar-width: 250px; --gap: 2rem; --container-max: 1200px; } .main-content { min-height: calc(100vh - var(--header-height) - var(--footer-height)); padding: var(--gap); } .content-area { width: calc(100% - var(--sidebar-width) - var(--gap)); } .responsive-container { width: min(var(--container-max), calc(100% - var(--gap) * 2)); margin-inline: auto; } Performans Notları /* ⚠️ Dikkat - Sürekli hesaplama */ .animated { /* Her frame'de hesaplanır */ width: calc(100% - 20px); transition: width 0.3s; } /* ✅ Daha iyi - Sabit değer */ :root { --dynamic-width: calc(100% - 20px); } .animated { width: var(--dynamic-width); transition: width 0.3s; } calc() modern tarayıcılarda çok hızlı, ancak karmaşık hesaplamalar (özellikle animasyonlarda) CPU kullanımını artırabilir. Kural: Modern layout için flex/grid kullan, calc() ince ayarlar için sakla. Yaygın Hatalar /* ❌ Parantez eksik */ width: calc 100% - 20px; /* ❌ Boşluk eksik */ width: calc(100%-20px); /* ❌ Birim eksik */ width: calc(100% - 20); /* ❌ Geçersiz bölme */ width: calc(100% / 50%); /* ❌ İç içe calc() - gereksiz */ width: calc(calc(100% - 20px) - 10px); /* ✅ Doğru - tek calc() yeterli */ width: calc(100% - 20px - 10px); width: calc(100% - 30px); Özet calc() fonksiyonu modern CSS'in en pratik araçlarından biri. Farklı birimleri birleştirerek, matematiksel hesaplamalar yaparak, responsive tasarımları kolaylaştırıyor. Özellikle: Custom properties ile güçlü Container/viewport birimler ile esnek min(), max(), clamp() ile kombine edilebilir Grid ve flexbox'ı tamamlar (yerini almaz) Performansı çok iyi Modern web'de calc() bilmeden responsive tasarım yapmak neredeyse imkansız!
-
- css
- css calc()
-
(and 1 more)
Tagged with:
-
Modern CSS'in en güçlü araçlarından ikisi olan min() ve max() fonksiyonları, responsive tasarımda dinamik değerler oluşturmamızı sağlıyor. Temel Mantık min() fonksiyonu: Verilen değerlerden en küçüğünü seçer max() fonksiyonu: Verilen değerlerden en büyüğünü seçer /* min() - en küçük değeri kullanır */ width: min(500px, 100%); /* Ekran 500px'den küçükse 100% kullanır, büyükse 500px kullanır */ /* max() - en büyük değeri kullanır */ width: max(300px, 50%); /* 50% değeri 300px'den küçükse 300px kullanır, büyükse 50% kullanır */ Gerçek Dünya Senaryoları 1. Maksimum Genişlik Sınırlaması (min ile) .container { /* Klasik yöntem */ width: 100%; max-width: 1200px; /* Modern yöntem - tek satırda */ width: min(1200px, 100%); /* veya daha esnek */ width: min(1200px, 100% - 2rem); /* yanlarda boşluk bırakır */ } Neden min() kullanıyoruz? Çünkü container'ın 1200px'i aşmamasını istiyoruz. Ekran küçülünce min() otomatik olarak daha küçük değeri (100%) seçer. 2. Minimum Genişlik Garantisi (max ile) .button { /* Buton asla 120px'den küçük olmayacak */ width: max(120px, 30%); /* Ekran çok küçükse bile minimum 120px kalır */ } .sidebar { /* Sidebar minimum 250px, ideal 20% genişlikte */ width: max(250px, 20vw); } 3. Tipografi ve Okuma Rahatlığı .article { /* Metin satırları optimal okuma için 65 karakter civarı */ max-width: min(65ch, 90%); /* ch birimi = 0 karakterinin genişliği */ } .heading { /* Başlıklar ekranda çok uzun açılmasın */ max-width: min(20ch, 100%); } 4. Responsive Padding/Margin .section { /* Küçük ekranda 5%, büyük ekranda max 60px */ padding-inline: min(5vw, 60px); } .card { /* Minimum 1rem, maksimum ekranın %3'ü kadar boşluk */ gap: min(3vw, 2rem); } Birden Fazla Değer Kullanma Her iki fonksiyon da 2'den fazla değer kabul eder: .responsive-box { /* 3 değerden en küçüğünü seç */ width: min(600px, 80%, 90vw); /* Pratik kullanım */ padding: min(5%, 3rem, 40px); } .flexible-grid { /* Grid kolonları için */ grid-template-columns: repeat(auto-fit, minmax( max(250px, 30%), /* minimum genişlik */ 1fr )); } Calc() ile Kombinasyon En güçlü kullanım calc() ile birleştirme: .smart-container { /* Ekran genişliğinin 90%'ı ama max 1400px, ve her iki yanda 2rem boşluk garantili */ width: min(1400px, 100% - 4rem); margin-inline: auto; } .dynamic-spacing { /* Ekran büyüdükçe artan ama sınırlı boşluk */ padding: max(1rem, min(5vw, 4rem)); } Avantajları Media Query Azaltır: Çoğu durumda breakpoint'e gerek kalmaz Daha Maintainable: Tek satırda responsive davranış tanımlanır Performans: Tarayıcı runtime'da hesaplar, JavaScript gerekmez Kapsayıcı Tasarım: Farklı ekran boyutları için doğal adaptasyon Karşılaştırma: Eski vs Yeni Yöntem /* ❌ Eski yöntem - media query gerekir */ .container { width: 100%; } @media (min-width: 1200px) { .container { width: 1200px; } } /* ✅ Modern yöntem - tek satır */ .container { width: min(1200px, 100%); } Tarayıcı Desteği Modern tarayıcıların tümü bu fonksiyonları destekliyor (2020'den beri). Eski tarayıcılar için fallback: .element { width: 90%; /* Fallback */ width: min(1200px, 90%); /* Modern tarayıcılar için */ } Özet min() ve max() fonksiyonları modern CSS'in intrinsic design (içsel tasarım) felsefesinin temel taşları. Media query yazmadan, JavaScript kullanmadan, sadece CSS ile gerçekten responsive ve akıllı layoutlar oluşturmamızı sağlıyorlar. Özellikle clamp() fonksiyonu ile birlikte kullanıldığında, modern web tasarımının vazgeçilmez araçları haline geliyorlar.
-
PHP'nin 30 yıllık evrimini derinlemesine inceleyelim. 1. Başlangıç Dönemi (1994-1997) PHP/FI (Personal Home Page / Forms Interpreter) - 1994 Rasmus Lerdorf tarafından kendi kişisel web sitesini yönetmek için C dilinde yazılan basit CGI scriptleri olarak başladı. İlk versiyonda: Basit değişken sistemi Form işleme yetenekleri Ziyaretçi sayacı gibi temel araçlar PHP/FI 2.0 - 1995-1996 SQL desteği eklendi (mSQL) Gerçek bir programlama dili haline gelmeye başladı Ancak hala çok sınırlı ve kişisel kullanıma yönelikti 2. Modern PHP'nin Temeli (1997-2000) PHP 3.0 - Haziran 1997 Zeev Suraski ve Andi Gutmans, PHP'yi tamamen yeniden yazdılar. Bu versiyon PHP'yi ciddi bir web programlama diline dönüştürdü. Önemli Yenilikler: Nesne yönelimli programlama desteği (çok basit düzeyde) Modüler genişletilebilir mimari Çok sayıda veritabanı desteği (MySQL, PostgreSQL, Oracle) ODBC desteği Üçüncü parti API'leri için destek Daha tutarlı sözdizimi Özellikler: // PHP 3'te basit class kullanımı class User { var $name; var $email; function setName($name) { $this->name = $name; } } PHP 4.0 - 22 Mayıs 2000 Zend Engine 1.0 ile geldi. Bu, PHP'nin performansını önemli ölçüde artırdı. Gelen Özellikler: Zend Engine: PHP'nin çekirdeği tamamen yeniden yazıldı Session yönetimi (built-in) Output buffering (ob_start, ob_get_contents) Gelişmiş array fonksiyonları Referanslar ve referans sayma sistemi HTTP_GET_VARS, HTTP_POST_VARS gibi süper global'ler (henüz $_GET yoktu) COM/DCOM desteği (Windows için) Java ile entegrasyon Perl Compatible Regular Expressions (PCRE) // Session kullanımı session_start(); $_SESSION['user_id'] = 123; // Output buffering ob_start(); echo "Bu buffer'da"; $content = ob_get_clean(); Sorunlar: OOP desteği hala çok zayıftı Objeler değer olarak kopyalanıyordu (referans değil) Namespace yoktu Exception handling yoktu 3. OOP Devrimi (2004-2009) PHP 5.0 - 13 Temmuz 2004 Zend Engine 2.0 ile geldi. PHP'yi modern bir OOP diline dönüştürdü. Devrim Niteliğinde Özellikler: 1. Gerçek OOP Desteği: // Visibility modifiers class User { private $password; protected $email; public $name; public function __construct($name) { $this->name = $name; } // Magic methods public function __toString() { return $this->name; } } // Inheritance class Admin extends User { public function deleteUser() { // ... } } // Interfaces interface Loggable { public function log($message); } // Abstract classes abstract class BaseController { abstract public function handle(); } 2. Exception Handling: try { throw new Exception("Bir hata oluştu"); } catch (Exception $e) { echo $e->getMessage(); } finally { // PHP 5.5'te eklendi // Cleanup } 3. Type Hinting (sadece class ve array): function processUser(User $user, array $options) { // ... } 4. Diğer Özellikler: Objeler artık referans olarak geçiliyor Iterators ve SPL (Standard PHP Library) Reflection API SimpleXML MySQLi (MySQL Improved Extension) PDO (PHP Data Objects) // PDO ile veritabanı $pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass'); $stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?'); $stmt->execute([1]); PHP 5.1 - 24 Kasım 2005 PDO varsayılan olarak aktif Performans iyileştirmeleri DateTime sınıfı PHP 5.2 - 2 Kasım 2006 JSON desteği (json_encode, json_decode) Zip archive desteği Filter extension (input validation) Improved memory management // JSON kullanımı $data = ['name' => 'Ali', 'age' => 25]; $json = json_encode($data); $decoded = json_decode($json, true); PHP 5.3 - 30 Haziran 2009 Çok önemli bir versiyon. Modern PHP'nin gerçek başlangıcı. Önemli Yenilikler: 1. Namespace: namespace App\Models; class User { // ... } // Kullanım use App\Models\User; $user = new User(); 2. Late Static Binding: class Parent { public static function who() { echo static::class; // PHP 5.3'te static:: } } class Child extends Parent {} Child::who(); // "Child" yazdırır 3. Closure (Anonim Fonksiyonlar): $multiply = function($x, $y) { return $x * $y; }; echo $multiply(3, 4); // 12 // use keyword ile dış scope'tan değişken kullanma $factor = 10; $multiplier = function($number) use ($factor) { return $number * $factor; }; 4. Diğer Özellikler: goto statement (tartışmalı) Nowdoc syntax (tek tırnaklı heredoc) __DIR__ magic constant Ternary shorthand: $x ?: 'default' Phar archives (PHP Archive) PHP 5.4 - 1 Mart 2012 Gelen Özellikler: 1. Traits: trait Logger { public function log($message) { echo $message; } } class User { use Logger; } $user = new User(); $user->log("Hello"); // Trait'ten gelen method 2. Short Array Syntax: // Eski $array = array(1, 2, 3); // Yeni $array = [1, 2, 3]; $assoc = ['name' => 'Ali', 'age' => 25]; 3. Built-in Web Server: php -S localhost:8000 4. Diğer Özellikler: Array dereferencing: function()[0] Callable type hint <?= always available (short echo tag) Binary number format: 0b001101 Session upload progress Çıkarılan Özellikler: register_globals - GÜVENLİK nedeniyle magic_quotes - GÜVENLİK nedeniyle safe_mode - GÜVENLİK nedeniyle PHP 5.5 - 20 Haziran 2013 1. Generators: function getNumbers() { for ($i = 0; $i < 1000; $i++) { yield $i; // Belleği şişirmeden büyük veri setleri } } foreach (getNumbers() as $number) { echo $number; } 2. finally Block: try { // kod } catch (Exception $e) { // hata } finally { // her durumda çalışır } 3. Password Hashing API: // Güvenli şifre hash'leme $hash = password_hash("mypassword", PASSWORD_DEFAULT); $verify = password_verify("mypassword", $hash); 4. Diğer: empty() ile expressions kullanımı Array and string literal dereferencing OPcache (APC'nin yerini aldı) ::class keyword echo User::class; // "User" string'ini döner PHP 5.6 - 28 Ağustos 2014 1. Variadic Functions: function sum(...$numbers) { return array_sum($numbers); } echo sum(1, 2, 3, 4); // 10 2. Argument Unpacking: $array = [1, 2, 3]; function add($a, $b, $c) { return $a + $b + $c; } echo add(...$array); // 6 3. Constant Expressions: const ARRAY = [1, 2, 3]; const TWO = 1 + 1; 4. Diğer: Exponential operator: 2 ** 3 = 8 use function ve use const Large file uploads (>2GB) phpdbg debugger 4. Modern PHP Çağı (2015-2020) PHP 7.0 - 3 Aralık 2015 DEVASA PERFORMANS ARTIŞI - Zend Engine 3.0 Bu versiyon PHP tarihindeki en önemli sıçramalardan biri. %50-200 performans artışı ve %50 bellek kullanımı azalması. Scalar Type Declarations: function add(int $a, int $b): int { return $a + $b; } declare(strict_types=1); // Strict mode Return Type Declarations: function getUser(): ?User { // Nullable return return null; } function getData(): array { return []; } Null Coalescing Operator: // Eski $name = isset($_GET['name']) ? $_GET['name'] : 'Guest'; // Yeni $name = $_GET['name'] ?? 'Guest'; Spaceship Operator: echo 1 <=> 2; // -1 echo 2 <=> 2; // 0 echo 3 <=> 2; // 1 // Sorting'te kullanımı usort($array, function($a, $b) { return $a <=> $b; }); Anonymous Classes: $logger = new class { public function log($message) { echo $message; } }; Group Use Declarations: use App\Models\{User, Post, Comment}; Diğer Özellikler: Unicode codepoint escape syntax: \u{1F602} Uniform variable syntax Throwable interface (Exception ve Error için ortak parent) Closure::call() Çıkarılanlar: mysql extension (mysqli ve PDO kullanılmalı) ereg extension (preg kullanılmalı) $HTTP_RAW_POST_DATA ASP ve script PHP tags: <% %>, <script language="php"> PHP 7.1 - 1 Aralık 2016 Nullable Types: function process(?string $name): ?int { return $name ? strlen($name) : null; } Void Return Type: function log(string $message): void { echo $message; } Symmetric Array Destructuring: // Short list syntax [$a, $b] = [1, 2]; // Keyed arrays ['name' => $name, 'age' => $age] = $user; Class Constant Visibility: class User { private const SECRET = 'hidden'; protected const CONFIG = 'protected'; public const VERSION = '1.0'; } Multi-catch: try { // kod } catch (TypeError | ValueError $e) { // Her ikisi için de aynı handler } Iterable Type: function process(iterable $data): void { foreach ($data as $item) { // array veya Traversable kabul eder } } PHP 7.2 - 30 Kasım 2017 Object Type Hint: function process(object $obj): object { return $obj; } Abstract Method Overriding: abstract class A { abstract function test(string $s); } abstract class B extends A { // Parameter type'ı kaldırabilir (daha esnek) abstract function test($s): int; } Parameter Type Widening: Child class'larda parent'ın type hint'i kaldırılabilir. Trailing Commas: $array = [ 'first', 'second', 'third', // Son virgül artık izinli ]; Diğer: count() ile non-countable için warning Sodium extension (modern kriptografi) Argon2 password hashing Deprecated: each() function (unset) cast __autoload() function PHP 7.3 - 6 Aralık 2018 Flexible Heredoc/Nowdoc: // Daha esnek indentation function test() { return <<<'END' Bu artık daha esnek END; } Array Destructuring with Reference: $array = [1, 2]; [&$a, $b] = $array; $a = 10; // $array artık [10, 2] is_countable() Function: if (is_countable($var)) { count($var); } Trailing Commas in Function Calls: function test($a, $b, $c) {} test( 1, 2, 3, // Artık izinli ); PHP 7.4 - 28 Kasım 2019 Bu versiyon modern PHP'nin temelini attı. Typed Properties: class User { public int $id; public string $name; public ?string $email = null; private array $roles; public function __construct(int $id) { $this->id = $id; } } Arrow Functions: // Eski $multiply = function($x) use ($factor) { return $x * $factor; }; // Yeni (otomatik use) $multiply = fn($x) => $x * $factor; // Array fonksiyonlarında $numbers = array_map(fn($n) => $n * 2, [1, 2, 3]); Null Coalescing Assignment: // Eski $data['key'] = $data['key'] ?? 'default'; // Yeni $data['key'] ??= 'default'; Array Spread Operator: $array1 = [1, 2, 3]; $array2 = [4, 5]; $result = [...$array1, ...$array2]; // [1, 2, 3, 4, 5] // Associative arrays (numeric keys için) $array = ['a' => 1, ...['b' => 2]]; Numeric Literal Separator: $number = 1_000_000; // Okunabilirlik için $hex = 0xFF_FF_FF; Weak References: $obj = new stdClass; $weakRef = WeakReference::create($obj); Covariant Returns & Contravariant Parameters: class Animal {} class Dog extends Animal {} class AnimalShelter { public function get(Dog $dog): Animal { return new Animal(); } } class DogShelter extends AnimalShelter { // Covariant return: daha spesifik dönebilir public function get(Dog $dog): Dog { return new Dog(); } } Preloading: Opcache'e dosyaları önceden yükleme - ciddi performans artışı. Deprecated: Nested ternary without parentheses array_key_exists() ile objects 5. Modern PHP ve Tür Sistemi (2020-2024) PHP 8.0 - 26 Kasım 2020 BÜYÜK YENİLİKLER DOLU VERSİYON JIT (Just-In-Time) Compiler: Belirli senaryolarda %30-40 performans artışı. Union Types: function process(int|float $number): int|float { return $number * 2; } class Number { private int|float $value; } Named Arguments: function createUser( string $name, string $email, bool $active = true, int $age = 18 ) {} // İstediğin parametreyi gönder createUser( email: 'ali@example.com', name: 'Ali', age: 25 ); Attributes (Annotations): #[Route('/users', methods: ['GET'])] #[Authenticated] class UserController { #[Cache(ttl: 3600)] public function index(): array { return []; } } // Reflection ile okuma $attributes = (new ReflectionClass(UserController::class)) ->getAttributes(Route::class); Match Expression: // Eski switch switch ($status) { case 'draft': $message = 'Taslak'; break; case 'published': $message = 'Yayında'; break; default: $message = 'Bilinmeyen'; } // Yeni match (daha güvenli, return eder) $message = match($status) { 'draft' => 'Taslak', 'published' => 'Yayında', default => 'Bilinmeyen', }; // Multiple conditions $result = match($value) { 1, 2, 3 => 'Küçük', 4, 5, 6 => 'Orta', default => 'Büyük', }; Constructor Property Promotion: // Eski class User { private string $name; private string $email; public function __construct(string $name, string $email) { $this->name = $name; $this->email = $email; } } // Yeni class User { public function __construct( private string $name, private string $email, ) {} } Nullsafe Operator: // Eski $country = null; if ($user !== null) { $address = $user->getAddress(); if ($address !== null) { $country = $address->country; } } // Yeni $country = $user?->getAddress()?->country; Mixed Type: function process(mixed $value): mixed { // Her şeyi kabul eder return $value; } Static Return Type: class Model { public static function create(): static { return new static(); } } Throw Expression: $value = $input ?? throw new Exception('Input required'); $callback = fn() => throw new Exception('Not implemented'); Weak Maps: $map = new WeakMap(); $obj = new stdClass; $map[$obj] = 'data'; // $obj silindiğinde map'ten de silinir Diğer: str_contains(), str_starts_with(), str_ends_with() get_debug_type() function ::class on objects Çıkarılanlar/Deprecated: Birçok eski, güvenli olmayan özellik PHP 8.1 - 25 Kasım 2021 Enums (Enumerations): // Pure enum enum Status { case Draft; case Published; case Archived; } $status = Status::Published; // Backed enum (değer içerir) enum Status: string { case Draft = 'draft'; case Published = 'published'; case Archived = 'archived'; } // Methods ve daha fazlası enum Status: string { case Draft = 'draft'; case Published = 'published'; public function label(): string { return match($this) { self::Draft => 'Taslak', self::Published => 'Yayında', }; } } $status = Status::from('draft'); // String'den enum Readonly Properties: class User { public function __construct( public readonly string $name, public readonly int $age, ) {} } $user = new User('Ali', 25); $user->name = 'Veli'; // HATA! Readonly değiştirilemez First-class Callable Syntax: // Eski $fn = Closure::fromCallable('strlen'); $fn = Closure::fromCallable([$obj, 'method']); // Yeni $fn = strlen(...); $fn = $obj->method(...); // Array functions ile array_map(strtoupper(...), $strings); Intersection Types: interface Loggable {} interface Cacheable {} function process(Loggable&Cacheable $obj) { // $obj her iki interface'i de implement etmeli } New in Initializers: class Service { public function __construct( private Logger $logger = new Logger(), ) {} } // Attribute'lerde de #[Route(new PathPrefix('/api'))] class ApiController {} Pure Intersection Types: function process((Countable&Iterator)|array $data) { // ... } Never Return Type: function redirect(string $url): never { header("Location: $url"); exit; } function throwException(): never { throw new Exception(); } Final Class Constants: class Config { final public const VERSION = '1.0'; } class ExtendedConfig extends Config { public const VERSION = '2.0'; // HATA! } Explicit Octal Notation: // Eski $octal = 0755; // Karışık // Yeni $octal = 0o755; // Açık ve net Fibers: Asenkron programlama için düşük seviye primitive: $fiber = new Fiber(function (): void { $value = Fiber::suspend('İlk değer'); echo "Devam ediyor: $value\n"; }); $fiber->start(); $fiber->resume('İkinci değer'); Diğer: Array unpacking with string keys array_is_list() function fsync(), fdatasync() Deprecated: Passing null to non-nullable internal function parameters Serializable interface PHP 8.2 - 8 Aralık 2022 Readonly Classes: readonly class User { public function __construct( public string $name, public int $age, ) {} // Tüm property'ler otomatik readonly } Disjunctive Normal Form (DNF) Types: // Karmaşık type combinations function process((Countable&ArrayAccess)|null $data) { // ... } class Repository { private (PDO&Loggable)|(mysqli&Loggable)|null $connection; } True Type: function isValid(): true { // Sadece true dönebilir, false dönemez return true; } Constants in Traits: trait HasVersion { public const VERSION = '1.0'; public function getVersion(): string { return self::VERSION; } } Deprecated Dynamic Properties: // Artık deprecated $obj = new stdClass; $obj->dynamicProperty = 'value'; // Deprecated warning // İzin vermek için #[AllowDynamicProperties] class MyClass {} Diğer: Random Extension (modern rastgele sayı üretimi) mysqli_execute_query() function curl_upkeep() Sensitive parameter redaction Deprecated: Dynamic properties (yukarıda belirtildi) utf8_encode() ve utf8_decode() ${var} string interpolation PHP 8.3 - 23 Kasım 2023 Typed Class Constants: class Config { public const string VERSION = '1.0'; public const int MAX_USERS = 100; private const array SETTINGS = []; } Override Attribute: class Parent { public function test(): void {} } class Child extends Parent { #[Override] // Parent'ta yoksa hata verir public function test(): void {} } Dynamic Class Constant Fetch: class Config { const string DEFAULT = 'value'; } $name = 'DEFAULT'; echo Config::{$name}; // Dynamic Anonymous Readonly Classes: $user = new readonly class('Ali', 25) { public function __construct( public string $name, public int $age, ) {} }; json_validate() Function: // JSON parse etmeden validation if (json_validate($string)) { $data = json_decode($string); } Negative Array Indices: $array = ['a', 'b', 'c']; $array[-1] = 'd'; // Son eleman Diğer: mb_str_pad() function stream_context_set_options() improvements Randomizer additions Command line linter supports multiple files Deprecated: Implicitly nullable parameter declarations MT_RAND_PHP mode PHP 8.4 - 21 Kasım 2024 (En Güncel) Property Hooks: class User { // Virtual property - backing field yok public string $fullName { get => $this->firstName . ' ' . $this->lastName; } // Lazy loading private array $data { get => $this->data ??= $this->loadData(); } // Validation public int $age { set(int $value) { if ($value < 0) { throw new ValueError(); } $this->age = $value; } } } Asymmetric Visibility: class User { // Public okunabilir, private yazılabilir public private(set) string $name; // Protected set public protected(set) int $age; public function __construct(string $name) { $this->name = $name; // Sadece sınıf içinde } } $user = new User('Ali'); echo $user->name; // OK $user->name = 'Veli'; // HATA! new Without Parentheses: // Eski $request = (new Request())->withMethod('POST'); // Yeni $request = new Request()->withMethod('POST'); HTML5 Support in DOM: $dom = DOM\HTMLDocument::createFromString($html, LIBXML_NOERROR); Array Find Functions: $array = [1, 2, 3, 4, 5]; // İlk eşleşeni bul $first = array_find($array, fn($n) => $n > 2); // 3 // İlk key'i bul $key = array_find_key($array, fn($n) => $n > 2); // 2 // any/all $hasEven = array_any($array, fn($n) => $n % 2 === 0); // true $allEven = array_all($array, fn($n) => $n % 2 === 0); // false #[Deprecated] Attribute: class OldClass { #[Deprecated( message: "Use NewClass instead", since: "2.0" )] public function oldMethod(): void {} } Lazy Objects: // Proxy pattern için built-in destek $user = new ReflectionClass(User::class) ->newLazyProxy(function() { return new User(); }); Diğer: request_parse_body() function PDO driver-specific subclasses OpenSSL EC key support bcround(), bcfloor(), bcceil() functions Özet: PHP'nin Evrimi Önemli Dönüm Noktaları: PHP 3 (1997): Gerçek programlama dili PHP 4 (2000): Zend Engine, session, performance PHP 5 (2004): Gerçek OOP PHP 5.3 (2009): Namespace, closure - Modern PHP başlangıcı PHP 7 (2015): Devasa performans artışı, scalar types PHP 8 (2020): JIT, union types, attributes PHP 8.1 (2021): Enums, readonly PHP 8.4 (2024): Property hooks, asymmetric visibility Genel Trendler: Performans: Her versiyonda sürekli iyileşme Tür Güvenliği: Gitgide güçlenen type system Modern OOP: C#/Java benzeri özelliklere yakınsama Güvenlik: Tehlikeli özelliklerin kaldırılması Developer Experience: Daha az kod, daha çok ifade gücü PHP artık eski "kötü" imajından çok uzak, modern, güvenli ve performanslı bir dil haline gelmiş durumda.
-
Pixel, CSS'in en eski ve en tartışmalı birimidir. "Absolute unit" olarak sınıflandırılsa da, aslında durum biraz daha karmaşık. Detaylı açıklayayım. 1. PX Nedir? (Teknik Gerçek) CSS Pixel ≠ Fiziksel Pixel CSS Pixel (Reference Pixel) ↓ Device Independent Pixel (DIP) ↓ Physical Pixel (gerçek ekran pikselleri) Önemli: 1px CSS'de her zaman aynı fiziksel boyut DEĞİLDİR! Pixel Density (DPR - Device Pixel Ratio) // Tarayıcı konsolunda console.log(window.devicePixelRatio); // Sonuçlar: // - Normal ekran: 1 (1 CSS px = 1 fiziksel pixel) // - Retina/HiDPI: 2 (1 CSS px = 4 fiziksel pixel - 2×2) // - 4K ekran: 3 veya 4 (1 CSS px = 9 veya 16 fiziksel pixel) Örnek: .line { border: 1px solid black; } Normal ekran (DPR=1): 1 fiziksel pixel kalınlığında Retina (DPR=2): 2 fiziksel pixel kalınlığında 4K (DPR=3): 3 fiziksel pixel kalınlığında Sonuç: 1px her cihazda yaklaşık aynı görsel boyutta görünür, ama farklı sayıda fiziksel pixel kullanır. 2. PX'in Tarihi ve Evolüsyonu 1990'lar - Mutlak Kontrol Dönemi /* O zamanlar herkes 800×600 veya 1024×768 ekran kullanıyordu */ body { width: 960px; /* Sabit genişlik */ font-size: 12px; margin: 0; padding: 0; } .header { height: 80px; } .content { width: 720px; float: left; } .sidebar { width: 240px; float: right; } ✅ O dönem için avantajlar: Pixel-perfect tasarım Öngörülebilir görünüm Basit hesaplama ❌ Sorunlar: Farklı çözünürlüklerde bozulma Responsive değil Erişilebilirlik sıfır 2000'ler - Responsive Farkındalık /* Media query'ler başladı */ .container { width: 960px; } @media (max-width: 768px) { .container { width: 100%; } } 2010'lar - Relative Units Yükselişi /* REM/EM/% popüler oldu */ html { font-size: 16px; /* Base */ } body { font-size: 1rem; /* 16px */ } h1 { font-size: 2.5rem; /* 40px */ } 2020+ Modern Dönem - Hybrid Yaklaşım /* PX hala kullanılıyor, ama doğru yerlerde */ .icon { width: 24px; /* Sabit boyut - OK */ } .container { max-width: 1200px; /* Maksimum sınır - OK */ padding: 2rem; /* Spacing - relative birim */ } h1 { font-size: clamp(2rem, 3vw + 1rem, 4rem); /* Fluid - relative */ } 3. PX Ne Zaman Kullanılmali? (Modern Yaklaşım) ✅ PX KULLAN - Doğru Kullanım Alanları 1. Border Width (Çerçeve Kalınlığı) /* ✅ DOĞRU - Border için px ideal */ .card { border: 1px solid #ccc; border-bottom: 2px solid blue; } /* ❌ YANLIŞ - REM ile border garip durur */ .card { border: 0.0625rem solid #ccc; /* 1px ama karmaşık */ } Neden px? Border her zaman keskin ve net olmalı 1px altı değerler anlamsız Kullanıcı font-size değiştirince border kalınlığı değişmemeli 2. Box Shadow (Gölgeler) /* ✅ DOĞRU */ .card { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } /* ✅ Daha büyük gölge */ .modal { box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2); } /* ❌ YANLIŞ - rem ile gölge değişir */ .card { box-shadow: 0 0.125rem 0.5rem rgba(0, 0, 0, 0.1); /* Kullanıcı font büyütünce gölge de büyür - garip */ } 3. Sabit Boyutlu Elementler (Icons, Avatars) /* ✅ İkonlar her zaman sabit boyut */ .icon { width: 24px; height: 24px; } .icon-small { width: 16px; height: 16px; } .icon-medium { width: 24px; height: 24px; } .icon-large { width: 32px; height: 32px; } .icon-xl { width: 48px; height: 48px; } /* ✅ Avatar'lar */ .avatar { width: 40px; height: 40px; border-radius: 50%; } /* ✅ Logo */ .logo { width: 180px; height: auto; } Neden px? İkonlar text boyutundan bağımsız olmalı Grid sistemlerde düzenli hizalama için Tasarım sisteminde tutarlılık 4. Max-Width Constraints (Maksimum Genişlik Sınırları) /* ✅ DOĞRU - Container max-width */ .container { width: 100%; /* Responsive */ max-width: 1200px; /* Ama çok büyük ekranlarda sınırla */ margin: 0 auto; } /* ✅ Content width */ .article { max-width: 65ch; /* Karakter bazlı (ideal) */ /* VEYA */ max-width: 700px; /* Pixel bazlı (da OK) */ } /* ✅ Modal width */ .modal { width: 90%; max-width: 600px; } Neden px? Tasarım kontrolü için üst sınır Çok geniş ekranlarda okunabilirlik Layout'un bozulmasını önle 5. Media Query Breakpoints /* ✅ DOĞRU - px breakpoint'ler yaygın */ /* Mobile first */ .grid { display: grid; grid-template-columns: 1fr; gap: 1rem; } @media (min-width: 640px) { /* sm */ .grid { grid-template-columns: repeat(2, 1fr); } } @media (min-width: 768px) { /* md */ .grid { grid-template-columns: repeat(3, 1fr); } } @media (min-width: 1024px) { /* lg */ .grid { grid-template-columns: repeat(4, 1fr); } } @media (min-width: 1280px) { /* xl */ .grid { grid-template-columns: repeat(5, 1fr); } } Alternatif - EM breakpoints: /* ✅ DA DOĞRU - em/rem daha erişilebilir */ @media (min-width: 40em) { /* 640px @ 16px base */ .grid { grid-template-columns: repeat(2, 1fr); } } @media (min-width: 48em) { /* 768px @ 16px base */ .grid { grid-template-columns: repeat(3, 1fr); } } Tartışma: PX: Viewport genişliğine göre (daha yaygın) EM: Kullanıcı font-size'ına da duyarlı (daha erişilebilir) 6. Çok Küçük Spacing Değerleri /* ✅ Çok küçük değerler için px daha net */ .divider { margin: 0; padding: 0; border-top: 1px solid #e0e0e0; } .tag { padding: 4px 8px; /* 0.25rem 0.5rem yerine */ border-radius: 3px; font-size: 0.75rem; } /* Grid gap çok küçükse */ .tight-grid { display: grid; gap: 8px; /* 0.5rem = 8px, ama px daha direkt */ } ❌ PX KULLANMA - Yanlış Kullanım Alanları 1. Font-Size (En Kritik Hata!) /* ❌ YANLIŞ - Erişilebilirlik ihlali */ html { font-size: 16px; } body { font-size: 14px; } h1 { font-size: 32px; } p { font-size: 16px; } Sorun: Kullanıcı tarayıcısında "Large fonts" seçse de değişmez Zoom yapınca oran bozulabilir WCAG erişilebilirlik kriterlerini ihlal eder /* ✅ DOĞRU - REM kullan */ html { font-size: 100%; /* 16px, ama kullanıcı ayarına saygılı */ } body { font-size: 1rem; /* 16px */ } h1 { font-size: 2rem; /* 32px */ /* VEYA fluid */ font-size: clamp(1.5rem, 3vw + 1rem, 3rem); } p { font-size: 1rem; } 2. Padding ve Margin (Spacing) /* ❌ YANLIŞ - Sabit spacing */ .section { padding: 60px 20px; margin-bottom: 40px; } .button { padding: 12px 24px; margin-right: 16px; } Sorun: Font-size değişince orantısız durur Responsive değil Komponentin iç tutarlılığı bozulur /* ✅ DOĞRU - Relative spacing */ .section { padding: 3.75rem 1.25rem; /* REM - global scale */ margin-bottom: 2.5rem; } .button { padding: 0.75em 1.5em; /* EM - component scale */ margin-right: 1em; font-size: 1rem; } EM vs REM Spacing: /* REM - Global consistency */ .card { padding: 2rem; /* Her zaman aynı (root'a göre) */ margin-bottom: 1.5rem; } /* EM - Component-based scaling */ .button-small { font-size: 0.875rem; padding: 0.5em 1em; /* Font-size'a göre ölçeklenir */ } .button-large { font-size: 1.25rem; padding: 0.5em 1em; /* Aynı em değeri, ama daha büyük */ } 3. Width ve Height (Layout) /* ❌ YANLIŞ - Sabit layout */ .sidebar { width: 300px; height: 600px; } .content { width: 900px; } Sorun: Responsive değil Farklı ekranlarda bozulur İçerik taşar /* ✅ DOĞRU - Flexible layout */ .layout { display: grid; grid-template-columns: 300px 1fr; /* Sidebar sabit OK, content flex */ gap: 2rem; } /* Veya tamamen flexible */ .layout { display: grid; grid-template-columns: minmax(250px, 300px) 1fr; gap: 2rem; } /* Mobil için responsive */ @media (max-width: 768px) { .layout { grid-template-columns: 1fr; } } 4. Line-Height /* ❌ YANLIŞ - Sabit line-height */ p { font-size: 16px; line-height: 24px; } h1 { font-size: 32px; line-height: 40px; } Sorun: Font-size değişince oran bozulur Responsive değil /* ✅ DOĞRU - Unitless veya relative */ p { font-size: 1rem; line-height: 1.5; /* Unitless - en iyi */ } h1 { font-size: 2rem; line-height: 1.2; } /* Veya em */ p { font-size: 1rem; line-height: 1.5em; /* Font-size × 1.5 */ } 4. PX vs Diğer Birimler - Karşılaştırma Font-Size Karşılaştırması /* Senaryo: Kullanıcı tarayıcıda font-size'ı 20px'e çıkardı */ /* PX - Değişmez (kötü) */ body { font-size: 16px; /* Hala 16px - kullanıcı tercihi görmezden gelindi */ } /* % - Kullanıcı tercihine uyar (iyi) */ html { font-size: 100%; /* 20px olur - kullanıcı ayarına uydu */ } /* REM - Root'a göre (en iyi) */ html { font-size: 100%; /* 20px */ } body { font-size: 1rem; /* 20px - kullanıcı ayarına uydu */ } h1 { font-size: 2rem; /* 40px - orantılı ölçeklendi */ } Spacing Karşılaştırması .component { font-size: 1rem; /* 16px → 20px (kullanıcı değiştirdi) */ } /* PX - Sabit kalır */ .px-spacing { padding: 16px 24px; /* Hala 16px 24px - orantısız */ } /* REM - Global scale */ .rem-spacing { padding: 1rem 1.5rem; /* 20px 30px - global scale ile ölçeklendi */ } /* EM - Component scale */ .em-spacing { padding: 1em 1.5em; /* 20px 30px - component font-size'a göre */ } Kullanıcı font-size artırınca: PX spacing: ┌────────────────┐ │ BUTTON │ ← Text büyük, padding küçük - sıkışık └────────────────┘ EM/REM spacing: ┌─────────────────────┐ │ BUTTON │ ← Her şey orantılı büyüdü └─────────────────────┘ 5. Modern Hybrid Yaklaşım Design System Örneği /* ========================================== MODERN DESIGN SYSTEM - HYBRID APPROACH ========================================== */ :root { /* ============= Sabit Değerler (PX) ============= */ /* Breakpoints */ --breakpoint-sm: 640px; --breakpoint-md: 768px; --breakpoint-lg: 1024px; --breakpoint-xl: 1280px; --breakpoint-2xl: 1536px; /* Container max-widths */ --container-sm: 640px; --container-md: 768px; --container-lg: 1024px; --container-xl: 1280px; /* Border widths */ --border-thin: 1px; --border-medium: 2px; --border-thick: 4px; /* Icon sizes */ --icon-xs: 16px; --icon-sm: 20px; --icon-md: 24px; --icon-lg: 32px; --icon-xl: 48px; /* ============= Relative Değerler (REM) ============= */ /* Spacing scale */ --space-xs: 0.25rem; /* 4px */ --space-sm: 0.5rem; /* 8px */ --space-md: 1rem; /* 16px */ --space-lg: 1.5rem; /* 24px */ --space-xl: 2rem; /* 32px */ --space-2xl: 3rem; /* 48px */ --space-3xl: 4rem; /* 64px */ /* Font sizes - Fluid */ --font-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem); --font-sm: clamp(0.875rem, 0.85rem + 0.13vw, 1rem); --font-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem); --font-lg: clamp(1.125rem, 1.05rem + 0.38vw, 1.313rem); --font-xl: clamp(1.25rem, 1.15rem + 0.5vw, 1.563rem); --font-2xl: clamp(1.5rem, 1.35rem + 0.75vw, 1.953rem); --font-3xl: clamp(1.875rem, 1.65rem + 1.13vw, 2.441rem); --font-4xl: clamp(2.25rem, 1.95rem + 1.5vw, 3.052rem); /* Border radius */ --radius-sm: 0.25rem; /* 4px */ --radius-md: 0.5rem; /* 8px */ --radius-lg: 1rem; /* 16px */ --radius-full: 9999px; } /* ============= Global Styles ============= */ html { font-size: 100%; /* Kullanıcı tercihine saygı */ } body { font-family: system-ui, -apple-system, sans-serif; font-size: var(--font-base); line-height: 1.6; color: #1a1a1a; } /* ============= Components ============= */ /* Button - EM ile component-based scaling */ .button { font-size: 1rem; padding: 0.5em 1em; /* EM - font-size'a göre */ border: var(--border-thin) solid; border-radius: var(--radius-md); /* REM */ cursor: pointer; transition: all 0.2s; } .button-sm { font-size: 0.875rem; padding: 0.5em 1em; /* Aynı em, ama küçük */ } .button-lg { font-size: 1.125rem; padding: 0.5em 1em; /* Aynı em, ama büyük */ } /* Card - REM ile global spacing */ .card { padding: var(--space-xl); /* REM - global scale */ border: var(--border-thin) solid #e0e0e0; /* PX - border */ border-radius: var(--radius-lg); box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); /* PX - shadow */ } /* Icon - PX ile sabit boyut */ .icon { width: var(--icon-md); /* PX - sabit */ height: var(--icon-md); display: inline-block; } /* Container - PX max-width, % width */ .container { width: 90%; /* % - responsive */ max-width: var(--container-xl); /* PX - üst sınır */ margin: 0 auto; padding: 0 var(--space-lg); /* REM - spacing */ } /* Grid - REM gap */ .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--space-xl); /* REM - consistent */ } /* Typography - Fluid + REM */ h1 { font-size: var(--font-4xl); /* Fluid clamp */ line-height: 1.1; /* Unitless */ margin-bottom: 0.5em; /* EM - font-size'a göre */ } h2 { font-size: var(--font-3xl); line-height: 1.2; margin-bottom: 0.5em; } p { font-size: var(--font-base); line-height: 1.6; margin-bottom: 1em; } /* ============= Utilities ============= */ /* Spacing utilities - REM */ .p-sm { padding: var(--space-sm); } .p-md { padding: var(--space-md); } .p-lg { padding: var(--space-lg); } .p-xl { padding: var(--space-xl); } .m-sm { margin: var(--space-sm); } .m-md { margin: var(--space-md); } .m-lg { margin: var(--space-lg); } .m-xl { margin: var(--space-xl); } /* Border utilities - PX */ .border { border: var(--border-thin) solid currentColor; } .border-2 { border: var(--border-medium) solid currentColor; } .border-4 { border: var(--border-thick) solid currentColor; } /* Icon sizes - PX */ .icon-sm { width: var(--icon-sm); height: var(--icon-sm); } .icon-md { width: var(--icon-md); height: var(--icon-md); } .icon-lg { width: var(--icon-lg); height: var(--icon-lg); } 6. PX Kullanımında Yaygın Hatalar Hata 1: Root Font-Size'ı PX ile Ayarlama /* ❌ EN BÜYÜK HATA */ html { font-size: 16px; } Neden kötü: Kullanıcının tarayıcı ayarlarını ezer Erişilebilirlik ihlali WCAG başarısız Bazı geliştiriciler bunu yapıyor: /* ❌ 10px base trick - YAPMA! */ html { font-size: 62.5%; /* 10px - kolay hesaplama için */ } body { font-size: 1.6rem; /* 16px */ } h1 { font-size: 3.2rem; /* 32px */ } Sorun: Tarayıcı varsayılanı 16px değilse bozulur Kullanıcı "Large fonts" seçmişse görmezden gelir Math zorlaştırma pahasına erişilebilirliği feda ediyorsun /* ✅ DOĞRU YOL */ html { font-size: 100%; /* Kullanıcı ayarına saygı */ } body { font-size: 1rem; /* 16px @ default */ } h1 { font-size: 2rem; /* 32px @ default - ama ölçeklenebilir */ } Hata 2: Her Yerde PX Kullanımı /* ❌ 2000'ler tarzı - modern değil */ .header { height: 80px; padding: 20px 40px; margin-bottom: 30px; } .nav-item { font-size: 14px; padding: 10px 15px; margin-right: 20px; } .content { font-size: 16px; line-height: 24px; padding: 40px; max-width: 800px; } Sorun: Hiçbir şey ölçeklenmiyor Responsive değil Bakımı zor /* ✅ Modern yaklaşım - mix */ .header { height: auto; /* İçeriğe göre */ padding: var(--space-lg) var(--space-xl); /* REM */ margin-bottom: var(--space-xl); /* REM */ } .nav-item { font-size: var(--font-sm); /* Fluid */ padding: 0.625em 0.9375em; /* EM - font'a göre */ margin-right: var(--space-md); /* REM */ } .content { font-size: var(--font-base); /* Fluid */ line-height: 1.5; /* Unitless */ padding: var(--space-2xl); /* REM */ max-width: 800px; /* PX - max OK */ } Hata 3: Media Query'lerde Sadece PX /* ⚠️ Yaygın ama tartışmalı */ @media (max-width: 768px) { .nav { display: block; } } Sorun: Kullanıcı font-size değiştirince layout kırılabilir 7. Özet - Modern PX Kullanım Rehberi ✅ PX Kullan: Border width - border: 1px solid Box shadow - box-shadow: 0 2px 8px Sabit boyutlu elementler - Icons, avatars, logos Max-width constraints - Container limits Media query breakpoints - (EM de OK) Transform offset - translateY(-2px) Çok küçük değerler - gap: 4px (ama REM daha iyi) ❌ PX Kullanma: Font-size - ASLA! Line-height - Unitless kullan Padding/Margin - REM veya EM kullan Width/Height (layout için) - Flexible units kullan Root font-size - % kullan (100%) ⚠️ Dikkatli Kullan: Border-radius - Küçükse PX OK, büyükse REM Gap - REM daha iyi ama PX de çalışır Min/Max values - Context'e göre 🎯 Altın Kural: "PX kullanacaksan, kendine sor: Bu değer kullanıcının font-size tercihinden etkilenmeli mi?" Evet ise → REM/EM/clamp() kullan Hayır ise → PX kullanabilirsin Modern web'de PX hala değerli bir araç, ama doğru yerde kullanılmalı. Her birim kendi amacı için optimize edilmiştir!
-
Yüzde birimi CSS'in en eski ve en esnek birimlerinden biri. CSS’in ilk günlerinden beri vardır. Ancak neye göre yüzde olduğu her property'de farklı! Detaylı açıklayayım. Responsive tasarım için idealdir. Parent boyutuna göre otomatik uyum sağlar. Tarayıcı yeniden boyutlandığında değerler otomatik güncellenir → reflow tetiklenir. 1. % Birimi Temel Mantığı % her zaman bir referans değere göre hesaplanır. .child { width: 50%; /* Neyin %50'si? */ } Cevap: Parent container'ın ilgili özelliğinin %50'si Ama dikkat: Her CSS property'de farklı referans noktası var! 2. Width ve Height için % Width - En Basit Kullanım .parent { width: 1000px; } .child { width: 50%; /* 1000px × 0.5 = 500px */ } Referans: Parent'ın width değeri Height - Karmaşık Durum /* ❌ ÇALIŞMAZ - Parent'ın height'ı auto */ .parent { /* height tanımlanmamış, içeriğe göre auto */ } .child { height: 50%; /* Neyin %50'si? Parent auto ise hesaplanamaz! */ } /* ✅ ÇALIŞIR - Parent'ın explicit height'ı var */ .parent { height: 600px; } .child { height: 50%; /* 600px × 0.5 = 300px */ } Önemli Kural: height: % çalışması için parent'ın kesin bir height'ı olmalı!. Çünkü height özelliği kalıtsal değildir. Modern Çözüm: Viewport Units /* Eski yöntem - sorunlu */ html, body { height: 100%; /* Chain oluştur */ } .container { height: 100%; } /* Modern yöntem - çok daha iyi */ .container { height: 100vh; /* Viewport height'ının %100'ü */ min-height: 100dvh; /* Dynamic viewport - mobil için */ } 3. Margin ve Padding için % Sürpriz: Her Zaman Width'e Göre Hesaplanır! .box { width: 400px; height: 600px; } .child { margin-top: 10%; /* 400px × 0.1 = 40px (width'e göre!) */ margin-left: 10%; /* 400px × 0.1 = 40px */ padding-top: 10%; /* 400px × 0.1 = 40px (height değil!) */ padding-bottom: 10%; /* 400px × 0.1 = 40px */ } Kritik: margin-top, margin-bottom, padding-top, padding-bottom bile parent'ın width'ine göre hesaplanır! Neden? Aspect Ratio Trickler İçin /* Eski aspect ratio trick (modern aspect-ratio property'den önce) */ .video-wrapper { width: 100%; padding-bottom: 56.25%; /* 16:9 aspect ratio = 9/16 = 0.5625 */ position: relative; background: black; } .video-wrapper iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } Mantık: Padding-bottom width'e göre olduğu için, genişlik değiştikçe yükseklik de orantılı değişir. Modern Alternatif: aspect-ratio /* Modern yöntem - çok daha temiz */ .video-wrapper { width: 100%; aspect-ratio: 16 / 9; background: black; } .video-wrapper iframe { width: 100%; height: 100%; } 4. Font-Size için % Referans: Parent'ın font-size'ı body { font-size: 16px; } .parent { font-size: 150%; /* 16px × 1.5 = 24px */ } .child { font-size: 50%; /* 24px × 0.5 = 12px */ } Root için % - Kullanıcı Tercihlerine Saygı /* ✅ EN İYİ PRATİK */ html { font-size: 100%; /* Tarayıcı varsayılanı (genelde 16px) */ /* Kullanıcı ayarlarını değiştirmişse ona uyar */ } body { font-size: 1rem; /* Root'un font-size'ı */ } Neden 100%? Kullanıcı tarayıcısında "Large fonts" seçmişse → 100% = 20px olur. Chrome tarayıcısnda Ayarlar > Görünüm Kullanıcı "Small fonts" seçmişse → 100% = 14px olur Erişilebilirlik için kritik! % vs REM vs EM /* % - Parent'a göre */ .parent { font-size: 16px; } .child { font-size: 150%; } /* 24px */ /* EM - Parent'a göre (aynı) */ .parent { font-size: 16px; } .child { font-size: 1.5em; } /* 24px */ /* REM - Root'a göre */ html { font-size: 16px; } .anywhere { font-size: 1.5rem; } /* Her zaman 24px */ Modern Tercih: REM (compound effect yok, öngörülebilir) 5. Position için % (Top, Right, Bottom, Left) Referans: Parent'ın İlgili Boyutu .parent { width: 400px; height: 600px; position: relative; } .child { position: absolute; top: 50%; /* Parent height'ının %50'si = 300px */ left: 25%; /* Parent width'ının %25'i = 100px */ width: 50%; /* Parent width'ının %50'si = 200px */ height: 30%; /* Parent height'ının %30'u = 180px */ } Merkezleme Trick (Transform ile) /* Klasik absolute merkezleme */ .centered { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); /* top/left: Parent'a göre %50 transform: Kendi boyutuna göre %-50 */ } Dikkat: transform: translate() içindeki % elementin kendi boyutuna göre! .box { width: 200px; height: 100px; transform: translateX(50%); /* 200px × 0.5 = 100px sağa */ transform: translateY(-50%); /* 100px × 0.5 = 50px yukarı */ } 6. Background-Position için % Sürpriz Davranış! .box { width: 400px; height: 300px; background-image: url('image.jpg'); /* 800×600px */ background-size: contain; background-position: 50% 50%; } % Hesaplaması: X pozisyonu = (container width - image width) × % Y pozisyonu = (container height - image height) × % /* Örnekler */ background-position: 0% 0%; /* Sol üst */ background-position: 100% 100%; /* Sağ alt */ background-position: 50% 50%; /* Tam orta */ /* 0% ve 100% özel durumlar */ background-position: 0% 0%; /* Resmin sol üstü, container'ın sol üstünde */ background-position: 100% 100%; /* Resmin sağ altı, container'ın sağ altında */ Background-Size için % .box { width: 400px; height: 300px; background-size: 50% 50%; /* Genişlik: 400px × 0.5 = 200px Yükseklik: 300px × 0.5 = 150px */ } /* Tek değer - orantılı */ background-size: 50%; /* Genişlik %50, yükseklik auto (orantılı) */ /* Modern alternatif */ background-size: cover; /* Tüm alanı kapla */ background-size: contain; /* İçine sığdır */ 7. Modern Web Tasarımda % Kullanım Alanları 1. Fluid Layouts (Akışkan Düzenler) /* ✅ Responsive Container */ .container { width: 90%; /* Ekranın %90'ı */ max-width: 1200px; /* Ama maximum 1200px */ margin: 0 auto; /* Ortala */ } /* ✅ Fluid Grid */ .grid { display: grid; grid-template-columns: 30% 70%; /* Sol sidebar, sağ content */ gap: 2%; } /* ❌ Artık bunu yapma - modern alternatif var */ .old-grid { float: left; width: 25%; margin-right: 5%; } Modern Alternatif - Flexbox/Grid: /* Flexbox ile daha iyi */ .flex-container { display: flex; gap: 2rem; } .sidebar { flex: 0 0 300px; /* Sabit genişlik */ } .content { flex: 1; /* Kalan alanı al */ } /* Grid ile en iyi */ .grid-container { display: grid; grid-template-columns: 300px 1fr; /* Sabit + esnek */ gap: 2rem; } 2. Responsive Images /* ✅ Temel responsive image */ img { max-width: 100%; /* Parent'tan taşma */ height: auto; /* Oranı koru */ } /* ✅ Fluid image container */ .image-wrapper { width: 100%; max-width: 600px; } .image-wrapper img { width: 100%; height: auto; } 3. Aspect Ratio Boxes (Eski Yöntem) /* ❌ Eski yöntem - padding trick */ .aspect-box { width: 100%; padding-bottom: 75%; /* 4:3 aspect ratio */ position: relative; background: #f0f0f0; } .aspect-box-content { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } /* ✅ Modern yöntem - aspect-ratio property */ .aspect-box-modern { width: 100%; aspect-ratio: 4 / 3; background: #f0f0f0; } 4. Typography - Line Height /* ✅ Line-height için % kullanımı */ p { font-size: 1rem; /* 16px */ line-height: 150%; /* 16px × 1.5 = 24px */ } /* ❌ Ama unitless daha iyi! */ p { font-size: 1rem; line-height: 1.5; /* Daha esnek, compound effect yok */ } Fark: /* % ile */ .parent { font-size: 16px; line-height: 150%; /* 24px hesaplanır ve sabitleşir */ } .child { font-size: 20px; /* line-height hala 24px - küçük kalır! */ } /* Unitless ile */ .parent { font-size: 16px; line-height: 1.5; /* Oran olarak kalır */ } .child { font-size: 20px; line-height: 1.5; /* 20px × 1.5 = 30px - orantılı! */ } 5. Opacity ve Colors /* % modern CSS'te bazı yerlerde kullanılıyor */ .element { opacity: 50%; /* 0.5 ile aynı */ background: rgb(255 0 0 / 50%); /* Alpha %50 */ } /* Ama geleneksel 0-1 arası daha yaygın */ .element { opacity: 0.5; background: rgba(255, 0, 0, 0.5); } 8. % vs Diğer Birimler - Ne Zaman Hangisi? Width/Height İçin /* % - Parent'a göre responsive */ .sidebar { width: 25%; /* Parent değişince değişir */ } /* vw/vh - Viewport'a göre */ .hero { height: 100vh; /* Her zaman viewport height'ı */ } /* px - Sabit boyut */ .icon { width: 24px; /* Her zaman aynı */ } /* fr (Grid için) - Kalan alanı böl */ .grid { grid-template-columns: 200px 1fr 2fr; /* 200px sabit, kalan alan 1:2 oranında bölünür */ } Font-Size İçin /* % - Parent'a göre (eski) */ html { font-size: 100%; } h1 { font-size: 200%; } /* REM - Root'a göre (modern tercih) */ html { font-size: 100%; } h1 { font-size: 2rem; } /* EM - Parent'a göre (spacing için iyi) */ .button { font-size: 1rem; padding: 0.5em 1em; /* Font-size değişince padding da değişir */ } /* clamp() - Fluid (en modern) */ h1 { font-size: clamp(1.5rem, 2vw + 1rem, 3rem); } Spacing İçin /* REM - Consistent spacing */ .section { padding: 2rem; /* Root font-size'a göre */ } /* EM - Component-based spacing */ .button { padding: 0.5em 1em; /* Butonun font-size'ına göre */ } /* % - Container'a göre (nadiren) */ .centered { margin: 0 10%; /* Sol/sağ %10 margin */ } /* vh/vw - Viewport'a göre */ .hero { padding: 10vh 5vw; /* Viewport boyutuna göre */ } 9. Modern Web'de % Best Practices ✅ KULLAN /* 1. Root font-size için */ html { font-size: 100%; /* Kullanıcı tercihlerine saygı */ } /* 2. Fluid container genişlikleri */ .container { width: 90%; max-width: 1400px; } /* 3. Responsive images */ img { max-width: 100%; height: auto; } /* 4. Grid column'ları (basit durumlar) */ .two-column { display: grid; grid-template-columns: 60% 40%; } /* 5. Transform translate */ .centered { transform: translate(-50%, -50%); } ⚠️ DİKKATLİ KULLAN /* 1. Height için (parent'ın height'ı kesin olmalı) */ .child { height: 80%; /* Parent'ın height'ı explicit mi? */ } /* 2. Padding/margin için (width'e göre hesaplandığını unutma) */ .box { padding-top: 10%; /* Height değil, width'e göre! */ } /* 3. Font-size için (REM daha iyi) */ .text { font-size: 125%; /* REM daha öngörülebilir */ } ❌ KULLANMA /* 1. Complex layouts (Flexbox/Grid daha iyi) */ .old-layout { float: left; width: 33.33%; margin-right: 2%; } /* Bunun yerine Grid kullan */ /* 2. Aspect ratios (modern property var) */ .old-ratio { padding-bottom: 56.25%; } /* Bunun yerine aspect-ratio kullan */ /* 3. Type scale (REM + clamp daha iyi) */ h1 { font-size: 250%; } /* Bunun yerine fluid typography */ 10. Gerçek Dünya Örnekleri Örnek 1: Modern Card Component /* ❌ Eski yöntem - % her yerde */ .card { width: 30%; margin: 1.5%; padding: 3%; float: left; } /* ✅ Modern yöntem - doğru birimleri kullan */ .card-container { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 2rem; padding: 2rem; } .card { padding: 1.5rem; /* % yerine rem/em - daha tutarlı */ } Örnek 2: Responsive Hero Section /* ✅ Modern yaklaşım - birimi amacına göre kullan */ .hero { /* Viewport units - tam ekran */ min-height: 100vh; min-height: 100dvh; /* Dynamic viewport - mobil için */ /* % - responsive spacing */ padding: 5vh 5%; /* max-width ile sınırla */ max-width: 1400px; margin: 0 auto; } .hero-title { /* Fluid typography - % değil */ font-size: clamp(2rem, 5vw + 1rem, 5rem); /* Unitless line-height */ line-height: 1.2; /* EM - font-size'a göre margin */ margin-bottom: 0.5em; } .hero-content { /* % - parent'a göre width */ width: 90%; max-width: 700px; margin: 0 auto; } Örnek 3: Responsive Image Gallery /* ✅ Modern grid + % kombinasyonu */ .gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 1rem; padding: 2rem; } .gallery-item { /* aspect-ratio modern, padding-bottom trick değil */ aspect-ratio: 1 / 1; overflow: hidden; } .gallery-item img { /* % - responsive image */ width: 100%; height: 100%; object-fit: cover; /* Hover effect - transform scale */ transition: transform 0.3s ease; } .gallery-item:hover img { transform: scale(1.1); /* %110 boyut */ } Modern Web'de % Felsefesi: Root font-size: 100% kullan (erişilebilirlik) Container width: % + max-width kombinasyonu Images: max-width: 100% responsive için Layouts: Flexbox/Grid tercih et (% yerine) Spacing: REM/EM kullan (% yerine) Typography: REM + clamp() (% yerine) % hala güçlü bir araç, ama artık "her şey için %" dönemi bitti. Her birimi amacına göre kullanmak modern yaklaşım! Hata : Height Yüzdesi Çalışmıyor /* ÇALIŞMAZ */ html, body { /* height: auto (default) *//* içerik kadar yükseklik */ } .full-height { height: 100%; /* Çalışmaz */ } /* ÇALIŞIR */ html, body { height: 100%; /* Burda parent(viewport) yükseklik(vh) devreye girer.*/ } .full-height { height: 100%; /* Şimdi çalışır. chain oluşacağı için tercih edilmez. */ } html elementinin parent’ı yoktur, ama rendering açısından tarayıcı onu viewport ile ilişkilendirir. Bu yüzden html { height: 100%; } → viewport yüksekliği(vh) kadar olur. Ardından body { height: 100%; } → html elementinin yüksekliği kadar olur → yani yine viewport yüksekliği. Eğer html’in height değeri tanımlı değilse, body { height: 100%; } işe yaramaz çünkü % birimi parent’a bağlıdır. Not: height olarak vh birimini kullanmak netlik sağlar ve belirsizliği giderir. width: 100%: % parent elementin iç genişliği → scrollbar hariçtir.
-
font-size, CSS’te bir metnin yazı tipi boyutunu belirleyen özelliktir. Yani sayfadaki bir yazının ne kadar büyük veya küçük görüneceğini kontrol edersin. Modern web geliştirmede font-size konusu ciddi bir evrim geçirdi. Detaylı açıklayayım. 1. Birimler ve Temel Kavramlar Absolute (Mutlak) Birimler /* PX - Pixel */ p { font-size: 16px; } ❌ Tarayıcı ayarlarına duyarlı değil ❌ Kullanıcı font tercihlerini görmezden gelir ✅ Kesin kontrol sağlar ⚠️ Erişilebilirlik sorunu /* PT, CM, MM - Baskı birimleri */ p { font-size: 12pt; } /* Sadece print için uygun */ Relative (Göreceli) Birimler /* EM - Parent'a göre */ .parent { font-size: 16px; } .child { font-size: 1.5em; } /* 16px × 1.5 = 24px */ .grandchild { font-size: 1.5em; } /* 24px × 1.5 = 36px - COMPOUND EFFECT! */ EM'in Tehlikesi - Cascading Problem: .article { font-size: 1.2em; } .article p { font-size: 1.1em; } .article p strong { font-size: 1.2em; } /* İç içe geçince: 1.2 × 1.1 × 1.2 = 1.584em - Kontrol kaybı! */ /* REM - Root'a göre (html elementi) */ html { font-size: 16px; } /* Base size */ h1 { font-size: 2rem; } /* Her zaman 32px */ p { font-size: 1rem; } /* Her zaman 16px */ ✅ **REM avantajları:** - Compound effect yok - Öngörülebilir - Kullanıcı font tercihleri çalışır - Tek bir yerden (root) tüm siteyi ölçeklendirebilirsin 2. Tarayıcının Varsayılan Yaklaşımı Tarayıcı Font-Size Hiyerarşisi 1. User Agent Stylesheet (Tarayıcı varsayılanı) └─ html { font-size: 16px; } 2. User Settings (Kullanıcı ayarları) └─ Tarayıcı ayarlarından font boyutu değiştirme 3. Author Stylesheet (Senin CSS'in) └─ Senin yazdığın kurallar Tarayıcı Varsayılan Font Boyutları /* Çoğu tarayıcının varsayılanı */ html { font-size: 16px; } h1 { font-size: 2em; } /* 32px */ h2 { font-size: 1.5em; } /* 24px */ h3 { font-size: 1.17em; } /* ~18.72px */ h4 { font-size: 1em; } /* 16px */ h5 { font-size: 0.83em; } /* ~13.28px */ h6 { font-size: 0.67em; } /* ~10.72px */ p { font-size: 1em; } /* 16px */ small { font-size: 0.875em; } /* 14px */ 3. Eski (Geleneksel) Yaklaşım 2000'ler - Pixel Tabanlı /* Eskiden herkes bunu yapardı */ body { font-size: 14px; } h1 { font-size: 28px; } p { font-size: 14px; } small { font-size: 12px; } ❌ Sorunlar: Sabit boyutlar Responsive değil Erişilebilirlik kötü Kullanıcı tercihleri çalışmaz 2010'lar - Em Tabanlı (İlk Responsive Dönem) body { font-size: 100%; } /* 16px */ h1 { font-size: 2em; } p { font-size: 1em; } @media (max-width: 768px) { body { font-size: 87.5%; } /* 14px */ } ⚠️ Sorun: Compound effect ve karmaşık hesaplamalar 4. Modern Yaklaşım (2020+) A) REM Tabanlı Sistem (En Yaygın) /* 1. Root'u % olarak ayarla (kullanıcı tercihlerine saygı) */ html { font-size: 100%; /* 16px, ama kullanıcı değiştirirse ona uyar */ } /* 2. Her şeyi REM ile tanımla */ :root { --font-xs: 0.75rem; /* 12px */ --font-sm: 0.875rem; /* 14px */ --font-base: 1rem; /* 16px */ --font-lg: 1.125rem; /* 18px */ --font-xl: 1.25rem; /* 20px */ --font-2xl: 1.5rem; /* 24px */ --font-3xl: 1.875rem; /* 30px */ --font-4xl: 2.25rem; /* 36px */ } body { font-size: var(--font-base); } h1 { font-size: var(--font-4xl); } h2 { font-size: var(--font-3xl); } p { font-size: var(--font-base); } small { font-size: var(--font-sm); } B) Fluid Typography (Akışkan Tipografi) Eski yöntem - Media Query'ler: h1 { font-size: 1.5rem; /* Mobile */ } @media (min-width: 768px) { h1 { font-size: 2rem; } /* Tablet */ } @media (min-width: 1024px) { h1 { font-size: 2.5rem; } /* Desktop */ } Modern yöntem - Clamp(): h1 { /* min: 1.5rem, ideal: viewport'a göre ölçeklen, max: 3rem */ font-size: clamp(1.5rem, 2vw + 1rem, 3rem); } /* Viewport genişliği arttıkça smooth geçiş */ C) Viewport Birimleri + Clamp (En Modern) :root { /* Fluid type scale */ --font-base: clamp(1rem, 0.5vw + 0.875rem, 1.125rem); --font-h1: clamp(2rem, 4vw + 1rem, 4rem); --font-h2: clamp(1.5rem, 3vw + 0.75rem, 3rem); --font-h3: clamp(1.25rem, 2vw + 0.5rem, 2rem); } body { font-size: var(--font-base); } h1 { font-size: var(--font-h1); } h2 { font-size: var(--font-h2); } h3 { font-size: var(--font-h3); } Clamp Formülü Açıklaması: font-size: clamp( 1rem, /* Minimum: Mobile'da bu */ 0.5vw + 0.875rem, /* İdeal: Viewport'a göre büyü */ 1.125rem /* Maximum: Çok büyük ekranlarda bu */ ); D) Container Query ile Font-Size (2024+) .card-container { container-type: inline-size; container-name: card; } .card h2 { font-size: 1rem; } /* Container 400px'den büyükse */ @container card (min-width: 400px) { .card h2 { font-size: 1.5rem; } } /* Container 600px'den büyükse */ @container card (min-width: 600px) { .card h2 { font-size: 2rem; } } 5. Responsive Font-Size Stratejileri Strateji 1: Type Scale (Modular Scale) :root { /* 1.25 ratio (Major Third) */ --ratio: 1.25; --font-xs: calc(1rem / var(--ratio) / var(--ratio)); /* 0.64rem */ --font-sm: calc(1rem / var(--ratio)); /* 0.8rem */ --font-base: 1rem; /* 1rem */ --font-lg: calc(1rem * var(--ratio)); /* 1.25rem */ --font-xl: calc(1rem * var(--ratio) * var(--ratio)); /* 1.563rem */ --font-2xl: calc(1rem * var(--ratio) * var(--ratio) * var(--ratio)); /* 1.953rem */ } /* Responsive ratio */ @media (min-width: 768px) { :root { --ratio: 1.333; /* Perfect Fourth - Tablet'te daha aggressive */ } } @media (min-width: 1024px) { :root { --ratio: 1.5; /* Perfect Fifth - Desktop'ta daha da aggressive */ } } Strateji 2: Utopia Fluid Type (Matematiksel Yaklaşım) :root { /* Minimum viewport: 320px */ /* Maximum viewport: 1240px */ --font-base: clamp( 1rem, /* 16px at 320px */ 0.913rem + 0.43vw, /* Fluid between */ 1.125rem /* 18px at 1240px */ ); --font-h1: clamp( 2rem, /* 32px at 320px */ 1.217rem + 3.91vw, /* Fluid between */ 4rem /* 64px at 1240px */ ); } Strateji 3: Step-Based System (Tailwind Tarzı) :root { /* Base boyut responsive */ --font-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem); /* Her step base'e göre */ --step--2: calc(var(--font-base) * 0.64); /* ~10-11px */ --step--1: calc(var(--font-base) * 0.8); /* ~13-14px */ --step-0: var(--font-base); /* 16-18px */ --step-1: calc(var(--font-base) * 1.25); /* 20-22px */ --step-2: calc(var(--font-base) * 1.563); /* 25-28px */ --step-3: calc(var(--font-base) * 1.953); /* 31-35px */ --step-4: calc(var(--font-base) * 2.441); /* 39-44px */ --step-5: calc(var(--font-base) * 3.052); /* 49-55px */ } /* Kullanım */ body { font-size: var(--step-0); } small { font-size: var(--step--1); } h4 { font-size: var(--step-2); } h3 { font-size: var(--step-3); } h2 { font-size: var(--step-4); } h1 { font-size: var(--step-5); } 6. Best Practices (2024) ✅ YAPILMASI GEREKENLER /* 1. Root'u asla px ile set etme */ html { font-size: 100%; /* DOĞRU */ /* font-size: 16px; - YANLIŞ */ } /* 2. REM kullan, px kullanma */ p { font-size: 1rem; /* DOĞRU */ /* font-size: 16px; - YANLIŞ */ } /* 3. Clamp ile smooth scaling */ h1 { font-size: clamp(1.5rem, 2vw + 1rem, 3rem); /* DOĞRU */ } /* 4. CSS Variables ile yönet */ :root { --font-body: clamp(1rem, 0.5vw + 0.875rem, 1.125rem); } body { font-size: var(--font-body); /* DOĞRU */ } /* 5. Line-height'ı da responsive yap */ p { font-size: clamp(1rem, 0.5vw + 0.875rem, 1.125rem); line-height: 1.6; /* Unitless - font-size'a göre ölçeklenir */ } ❌ YAPILMAMASI GEREKENLER /* 1. Root'u px ile ayarlama */ html { font-size: 16px; /* YANLIŞ - Kullanıcı tercihlerini ezer */ } /* 2. Her yerde px kullanma */ p { font-size: 14px; /* YANLIŞ */ padding: 10px; /* YANLIŞ */ margin: 20px; /* YANLIŞ */ } /* 3. Em'i font-size için kullanma (compound effect) */ .nested { font-size: 1.2em; /* RİSKLİ - İç içe geçince sorun */ } /* 4. Çok fazla breakpoint */ h1 { font-size: 1.5rem; } @media (min-width: 480px) { h1 { font-size: 1.75rem; } } @media (min-width: 768px) { h1 { font-size: 2rem; } } @media (min-width: 1024px) { h1 { font-size: 2.5rem; } } @media (min-width: 1280px) { h1 { font-size: 3rem; } } /* Bunun yerine clamp() kullan! */ 7. Gerçek Dünya Örneği Production-Ready Font System /* ============================================ MODERN FLUID TYPE SYSTEM ============================================ */ /* 1. Root ayarları */ html { font-size: 100%; /* 16px, ama kullanıcıya saygılı */ /* Smooth scroll için bonus */ scroll-behavior: smooth; } /* 2. CSS Custom Properties */ :root { /* Base fluid size */ --fluid-base: clamp(1rem, 0.913rem + 0.43vw, 1.125rem); /* Type scale - fluid */ --fluid-xs: clamp(0.75rem, 0.69rem + 0.29vw, 0.875rem); --fluid-sm: clamp(0.875rem, 0.826rem + 0.25vw, 1rem); --fluid-lg: clamp(1.125rem, 1.038rem + 0.43vw, 1.313rem); --fluid-xl: clamp(1.25rem, 1.109rem + 0.7vw, 1.563rem); --fluid-2xl: clamp(1.5rem, 1.283rem + 1.09vw, 1.953rem); --fluid-3xl: clamp(1.875rem, 1.543rem + 1.66vw, 2.441rem); --fluid-4xl: clamp(2.25rem, 1.826rem + 2.12vw, 3.052rem); --fluid-5xl: clamp(2.75rem, 2.174rem + 2.88vw, 3.815rem); } /* 3. Global typography */ body { font-family: system-ui, -apple-system, sans-serif; font-size: var(--fluid-base); line-height: 1.6; color: #1a1a1a; } /* 4. Headings */ h1, h2, h3, h4, h5, h6 { line-height: 1.2; font-weight: 700; margin-top: 0; margin-bottom: 0.5em; } h1 { font-size: var(--fluid-5xl); } h2 { font-size: var(--fluid-4xl); } h3 { font-size: var(--fluid-3xl); } h4 { font-size: var(--fluid-2xl); } h5 { font-size: var(--fluid-xl); } h6 { font-size: var(--fluid-lg); } /* 5. Body text elements */ p { font-size: var(--fluid-base); margin-bottom: 1em; } small { font-size: var(--fluid-sm); } /* 6. Utility classes */ .text-xs { font-size: var(--fluid-xs); } .text-sm { font-size: var(--fluid-sm); } .text-base { font-size: var(--fluid-base); } .text-lg { font-size: var(--fluid-lg); } .text-xl { font-size: var(--fluid-xl); } .text-2xl { font-size: var(--fluid-2xl); } .text-3xl { font-size: var(--fluid-3xl); } .text-4xl { font-size: var(--fluid-4xl); } .text-5xl { font-size: var(--fluid-5xl); } /* 7. Print styles */ @media print { html { font-size: 12pt; } h1 { font-size: 24pt; } h2 { font-size: 20pt; } h3 { font-size: 18pt; } p { font-size: 12pt; } } /* 8. Reduced motion için */ @media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } } 8. Özet - Modern Yaklaşım Checklist ✅ Root'u % olarak ayarla → Kullanıcı tercihlerine saygı ✅ REM kullan → Öngörülebilir, compound effect yok ✅ Clamp() ile fluid typography → Smooth responsive geçişler ✅ CSS Variables ile merkezi yönetim → Kolay bakım ✅ Type scale sistemi → Tutarlı hiyerarşi ✅ Line-height unitless → Font-size ile ölçeklensin ✅ Container queries → Component-bazlı responsive ❌ PX kullanma (root ve font-size için) ❌ EM ile font-size (spacing için kullanabilirsin) ❌ Çok fazla breakpoint (clamp kullan) ❌ Sabit değerler (fluid olsun) Modern web'de font-size artık sadece "boyut" değil, erişilebilirlik, responsive tasarım ve kullanıcı deneyiminin kesişim noktası!
-
clamp() fonksiyonu, modern CSS'in en güçlü ve kullanışlı araçlarından biri. Responsive tasarımda "fluid but constrained" (akışkan ama sınırlı) değerler oluşturmanıza olanak tanır. clamp() Nedir? clamp() üç parametre alır ve ortadaki değeri, minimum ve maksimum sınırlar arasında tutar: clamp(MIN, PREFERRED, MAX) Mantık: Eğer PREFERRED < MIN ise → MIN kullanılır Eğer PREFERRED > MAX ise → MAX kullanılır Eğer MIN ≤ PREFERRED ≤ MAX ise → PREFERRED kullanılır /* Basit örnek */ font-size: clamp(16px, 4vw, 32px); /* Anlamı: - Minimum 16px - Tercih edilen: viewport genişliğinin %4'ü - Maksimum 32px */ clamp() vs min() vs max() CSS'de üç benzer fonksiyon var, farkları anlamak önemli: /* max() - En büyük değeri seç */ width: max(300px, 50%); /* 300px veya %50'den hangisi büyükse onu kullan */ /* min() - En küçük değeri seç */ width: min(500px, 100%); /* 500px veya %100'den hangisi küçükse onu kullan */ /* clamp() - Aralıkta tut */ width: clamp(300px, 50%, 500px); /* %50 kullan, ama 300px'den küçük olmasın, 500px'den büyük olmasın */ Pratik Karşılaştırma: .container { /* Sadece max() */ width: max(320px, 50vw); /* Problem: Üst sınır yok, çok büyüyebilir */ /* Sadece min() */ width: min(1200px, 90vw); /* Problem: Alt sınır yok, çok küçülebilir */ /* clamp() - En güvenli */ width: clamp(320px, 90vw, 1200px); /* Perfect: Hem alt hem üst sınır var */ } Modern Web'de clamp() Kullanım Alanları 1. Fluid Typography (En Popüler Kullanım) Eski yöntem vs Modern yöntem: /* ❌ ESKİ YÖNTEM - Media Query Cehenemi */ h1 { font-size: 24px; } @media (min-width: 640px) { h1 { font-size: 32px; } } @media (min-width: 768px) { h1 { font-size: 40px; } } @media (min-width: 1024px) { h1 { font-size: 48px; } } @media (min-width: 1280px) { h1 { font-size: 56px; } } /* ✅ MODERN YÖNTEM - Tek Satır */ h1 { font-size: clamp(24px, 5vw + 1rem, 56px); } Gerçek Dünya Tipografi Sistemi: /* Typography Scale with clamp() */ :root { /* Base */ --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem); --text-sm: clamp(0.875rem, 0.825rem + 0.25vw, 1rem); --text-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem); --text-lg: clamp(1.125rem, 1.05rem + 0.375vw, 1.25rem); --text-xl: clamp(1.25rem, 1.15rem + 0.5vw, 1.5rem); /* Headings */ --text-2xl: clamp(1.5rem, 1.3rem + 1vw, 2rem); --text-3xl: clamp(1.875rem, 1.5rem + 1.875vw, 2.5rem); --text-4xl: clamp(2.25rem, 1.75rem + 2.5vw, 3rem); --text-5xl: clamp(3rem, 2rem + 5vw, 4rem); --text-6xl: clamp(3.75rem, 2.5rem + 6.25vw, 5rem); } body { font-size: var(--text-base); } h1 { font-size: var(--text-5xl); } h2 { font-size: var(--text-4xl); } h3 { font-size: var(--text-3xl); } h4 { font-size: var(--text-2xl); } h5 { font-size: var(--text-xl); } h6 { font-size: var(--text-lg); } 2. Responsive Spacing (Padding, Margin, Gap) /* Section spacing */ .section { padding-block: clamp(2rem, 5vw, 8rem); padding-inline: clamp(1rem, 5vw, 4rem); } /* Container padding */ .container { padding: clamp(1rem, 2vw + 0.5rem, 3rem); gap: clamp(1rem, 3vw, 2rem); } /* Grid gap */ .grid { display: grid; gap: clamp(1rem, 2vw, 3rem); grid-template-columns: repeat(auto-fit, minmax(clamp(250px, 30vw, 350px), 1fr)); } Gerçek Dünya Spacing Sistemi: :root { /* Spacing Scale */ --space-3xs: clamp(0.25rem, 0.23rem + 0.11vw, 0.3125rem); --space-2xs: clamp(0.5rem, 0.48rem + 0.11vw, 0.5625rem); --space-xs: clamp(0.75rem, 0.7rem + 0.22vw, 0.875rem); --space-s: clamp(1rem, 0.96rem + 0.22vw, 1.125rem); --space-m: clamp(1.5rem, 1.43rem + 0.33vw, 1.6875rem); --space-l: clamp(2rem, 1.91rem + 0.43vw, 2.25rem); --space-xl: clamp(3rem, 2.87rem + 0.65vw, 3.375rem); --space-2xl: clamp(4rem, 3.83rem + 0.87vw, 4.5rem); --space-3xl: clamp(6rem, 5.74rem + 1.3vw, 6.75rem); /* One-up pairs */ --space-3xs-2xs: clamp(0.25rem, 0.12rem + 0.65vw, 0.5625rem); --space-2xs-xs: clamp(0.5rem, 0.37rem + 0.65vw, 0.875rem); --space-xs-s: clamp(0.75rem, 0.59rem + 0.76vw, 1.125rem); --space-s-m: clamp(1rem, 0.74rem + 1.3vw, 1.6875rem); --space-m-l: clamp(1.5rem, 1.17rem + 1.63vw, 2.25rem); --space-l-xl: clamp(2rem, 1.48rem + 2.61vw, 3.375rem); --space-xl-2xl: clamp(3rem, 2.35rem + 3.26vw, 4.5rem); --space-2xl-3xl: clamp(4rem, 2.96rem + 5.22vw, 6.75rem); } 3. Responsive Width/Height /* Container genişlikleri */ .container-sm { width: clamp(320px, 90vw, 640px); margin-inline: auto; } .container-md { width: clamp(320px, 90vw, 768px); margin-inline: auto; } .container-lg { width: clamp(320px, 90vw, 1024px); margin-inline: auto; } .container-xl { width: clamp(320px, 90vw, 1280px); margin-inline: auto; } /* Card boyutları */ .card { width: clamp(280px, 100%, 400px); min-height: clamp(200px, 30vh, 400px); } /* Hero yükseklikleri */ .hero { min-height: clamp(400px, 70vh, 800px); } 4. Border Radius /* Responsive border radius */ .card { border-radius: clamp(0.5rem, 1vw, 1.5rem); } .button { border-radius: clamp(0.25rem, 0.5vw, 0.75rem); } /* Pill button */ .pill { border-radius: clamp(1rem, 3vw, 3rem); } 5. Icon ve Image Sizes /* Responsive icon */ .icon { width: clamp(20px, 3vw, 48px); height: clamp(20px, 3vw, 48px); } /* Logo boyutu */ .logo { height: clamp(32px, 5vw, 64px); width: auto; } /* Avatar */ .avatar { width: clamp(40px, 8vw, 80px); height: clamp(40px, 8vw, 80px); border-radius: 50%; } 6. Line Height ve Letter Spacing /* Responsive line height */ body { font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem); line-height: clamp(1.5, 1.4 + 0.2vw, 1.8); } h1 { font-size: clamp(2rem, 5vw, 4rem); line-height: clamp(1.1, 1 + 0.5vw, 1.3); letter-spacing: clamp(-0.02em, -0.01em + -0.01vw, -0.04em); } /* Tracking için */ .heading { letter-spacing: clamp(-0.05em, -0.02vw, -0.01em); } clamp() Best Practices ✅ YAPMASI GEREKENLER: /* 1. Accessibility - rem kullan */ font-size: clamp(1rem, 2vw, 2rem); /* ✅ */ font-size: clamp(16px, 2vw, 32px); /* ❌ Zoom'da sorun */ /* 2. Fallback düşün */ .element { font-size: 18px; /* Fallback */ font-size: clamp(1rem, 2vw, 2rem); /* Enhancement */ } /* 3. CSS custom properties ile */ :root { --fluid-text: clamp(1rem, 2vw, 1.5rem); } body { font-size: var(--fluid-text); } /* 4. Mantıklı aralıklar */ font-size: clamp(1rem, 2vw, 2rem); /* ✅ 2x büyüme */ font-size: clamp(1rem, 10vw, 10rem); /* ❌ 10x çok fazla */ /* 5. Viewport + static kombinasyon */ padding: clamp(1rem, 5vw + 1rem, 5rem); /* ✅ Base + fluid */ ❌ YAPILMAMASI GEREKENLER: /* 1. Çok küçük min değerler */ font-size: clamp(0.1rem, 2vw, 2rem); /* ❌ Okunamaz */ /* 2. Viewport-only preferred */ width: clamp(200px, 100vw, 1200px); /* ⚠️ Scrollbar sorunu */ width: clamp(200px, 90vw, 1200px); /* ✅ Daha güvenli */ /* 3. Negative values with vw */ margin: clamp(-2rem, -5vw, -1rem); /* ⚠️ Beklenmedik sonuçlar */ /* 4. Çok karmaşık hesaplamalar */ font-size: clamp( calc(1rem + 0.5vw), calc(2vw + 1rem + 0.5vh), calc(3rem + 1vw - 0.25rem) ); /* ❌ Debug edilemez */ /* 5. Her property için clamp */ .element { width: clamp(...); height: clamp(...); padding: clamp(...); margin: clamp(...); font-size: clamp(...); line-height: clamp(...); border-radius: clamp(...); /* ❌ Çok fazla, performans sorunu */ } Browser Support clamp() desteği çok iyi (2020'den beri): Chrome 79+ Firefox 75+ Safari 13.1+ Edge 79+ Özet clamp() modern web tasarımın vazgeçilmezi: Avantajları: Media query sayısını dramatik azaltır Gerçekten fluid responsive tasarım Accessibility dostu (doğru kullanıldığında) Kod okunabilirliği artırır Maintenance kolaylaşır Performance iyileşir (daha az media query) Dikkat Edilmesi Gerekenler: rem kullanımına dikkat (accessibility) Mantıklı min/max değerler seçin Fallback stratejisi düşünün Çok karmaşık hesaplamalardan kaçının Performance'ı göz önünde bulundurun clamp() ile artık her ekran boyutu için ayrı CSS yazmak yerine, matematiksel olarak mükemmel, fluid ve responsive tasarımlar oluşturabilirsiniz!
-
Viewport Nedir? Viewport, tarayıcıda web sayfasının görünen alanıdır. Basitçe söylemek gerekirse, kullanıcının ekranında gördüğü sayfa bölgesidir. Dolayısıyla pencereyi küçültüp büyüttükçe bu değerler dinamik olarak yeniden hesaplanır. Viewport değişince CSS’te: vw, vh, vmin, vmax, svh, lvh, dvh gibi birimler yeniden hesaplanır. Media queries tetiklenir. Container queries yeniden değerlendirilir. Safe-area env variables güncellenebilir. Relative units (% / em / rem) dolaylı olarak etkilenir. Çıkış sebebi: Mobil cihazlar ve farklı ekran çözünürlükleri. İhtiyaç: Esnek, responsive tasarım, okunabilirlik, tam ekran bölümler. Desktop vs Mobil Viewport Desktop'ta: Viewport genellikle tarayıcı penceresinin boyutuna eşittir (vw viewport genişliğidir → scrollbar varsa, dahil edilir.). Mobil cihazlarda: Durum biraz daha karmaşıktır çünkü ekran küçüktür. Ekran boyutu, genellikle dinamik olarak değişir (adres çubuğu açılınca kapanır vs). Viewport Meta Tag'i HTML'de viewport kontrolü için <head> bölümüne şu meta tag'i eklenir: <meta name="viewport" content="width=device-width, initial-scale=1.0"> Bu Tag'in Parametreleri: width=device-width Sayfanın genişliğini cihazın ekran genişliğine eşitler Bu sayede mobil cihazlarda sayfa doğru boyutta görünür initial-scale=1.0 Sayfa ilk yüklendiğinde zoom seviyesini belirler 1.0 = %100 zoom (yakınlaştırma/uzaklaştırma yok) Diğer Parametreler: <meta name="viewport" content=" width=device-width, initial-scale=1.0, maximum-scale=5.0, minimum-scale=1.0, user-scalable=yes "> maximum-scale: Maksimum zoom seviyesi minimum-scale: Minimum zoom seviyesi user-scalable: Kullanıcının zoom yapıp yapamayacağı (yes/no) Neden Önemli? Viewport meta tag'i olmadan, mobil tarayıcılar sayfayı desktop genişliğinde (genellikle 980px) render eder ve küçültür. Bu durumda: Yazılar çok küçük görünür Kullanıcı sürekli zoom yapmak zorunda kalır Mobil deneyim kötü olur Viewport meta tag'i ile responsive tasarım yapabilir, her cihazda optimize görünüm sağlarsın. Modern web tasarımında viewport-relative units (görünüm alanı göreli birimleri), responsive tasarımın temel taşlarından biri. Her birimin kendine özgü kullanım senaryoları ve dikkat edilmesi gereken noktalar var. Meta viewport yoksa birimler çalışır, ama mobilde ölçümler güvenilir olmayabilir. Modern responsive tasarımda mobil uyumluluk için meta viewport mutlaka kullanılır. Temel Viewport Birimleri Birimler; Dil veya yazı yönüne göre değişmez. İçerik genişliği yada yüksekliğine göre değişmez. vw (Viewport Width): Viewport genişliğinin(yatay ekran) %1'i anlamına gelir. 100vw = Viewport'un tam genişliği 50vw = Viewport genişliğinin yarısı .hero-section { width: 100vw; /* Tam genişlik */ font-size: 5vw; /* Responsive tipografi */ } Kullanım Alanları: Full-width layoutlar Fluid tipografi Responsive spacing sistemleri Olumsuz Yönleri: Scrollbar sorunu: 100vw genişlik, vertical scrollbar'ı hesaba katmaz. Eğer sayfada scrollbar varsa, yatay scrollbar oluşur. (yaklaşık 15-17px taşma). dikey scrollbar oluşmuşsa 100vw içinde scrollbarda olur. Bu durumda, width: 100vw-20px Mobile browser bar'lar: Mobil tarayıcılarda adres çubuğu viewport hesabını karıştırabilir. Mobilde Portrait (dikey): 100vw cihazın dikey moddaki dar kenarı kadar olur. Mobilde Landscape (yatay): 100vw cihazın yatay moddaki geniş kenarı kadar olur. 👉 Yani cihazı çevirdiğinde vw değeri değişir çünkü viewport genişliği değişir. /* Scrollbar sorunu çözümü */ .full-width { width: 100%; max-width: 100vw; overflow-x: hidden; } vh (Viewport Height): Viewport yüksekliğinin %1'i. .hero { height: 100vh; /* Tam ekran yükseklik */ } Olumsuz Yönleri: Mobile browser sorunları: iOS Safari ve benzeri mobile tarayıcılarda adres çubuğu görünüp kaybolduğunda 100vh sürekli değişir, bu da layout shift'lere neden olur. Landscape mode sorunları: Yatay modda yükseklik çok düşük olabilir, içerik taşabilir. Keyboard açıldığında: Mobilde keyboard açıldığında viewport height küçülür, layout bozulabilir. /* Mobile için daha güvenli yaklaşım */ .hero { min-height: 100vh; min-height: 100dvh; /* Dynamic viewport height */ } vh ve vw birimleri pencere boyutuna göre değişir. Modern tasarımlarda dvh gibi yeni birimler kullanmak en temiz çözümdür. vmin & vmax: vmin: Viewport'un en küçük boyutunun %1'i, vmin aslında min(vw, vh) şeklinde düşünülebilir. vmax: Viewport'un en büyük boyutunun %1'i, vmax ise max(vw, vh) şeklinde düşünülebilir. Mobilde: Portrait (dikey mod) Genişlik > Yükseklik: vmin = genişlik, vmax = yükseklik Landscape (yatay mod) Genişlik > Yükseklik: vmin = yükseklik, vmax = genişlik Desktop’ta orientation değişmez ama pencereyi çok yatay veya çok dikey yaparsan küçük/büyük kenar değişir. vmin ve vmax modern tasarımda fluid (akışkan) ve responsively ölçeklenen öğeler oluşturmak için çok kritik iki birimdir. Çünkü bu iki birim ekranda hangi kenarın baskın olduğunu otomatik algılar ve ona göre boyut verir. Kullanım alanları: h1 { font-size: 8vmin; /* Hem geniş hem dar ekranda orantılı büyür */ } Avantaj: Mobilde çok büyümez, masaüstünde çok küçülmez. Tasarımı sabit piksel bağımlılığından kurtarır. .square { width: 50vmin; height: 50vmin; /* Her zaman kare kalır */ } .adaptive-text { font-size: 3vmax; /* Hem portrait hem landscape'de okunabilir */ } Neden vmin? Çünkü kısa kenara göre hesaplar → daire hiçbir ekranda ezilmez. .hero-title { font-size: 10vmax; /* Geniş monitörde büyük, telefonda daha küçük */ } Neden vmax? Uzun kenara göre hesaplar → geniş ekranda etkili, devasa başlıklar sağlar. .section { padding: 5vmin; } Mobilde “çok doldurmaz”, geniş ekranda “çok boşaltmaz”. Tamamen oranlıdır. vmin: kare/daire, fluid font, responsive spacing vmax: hero başlıkları, geniş ekran tasarımları, dramatik boyutlar Kullanım Senaryoları: Aspect ratio korumak istediğinizde Orientation-independent tasarımlar Olumsuz Yönleri: Tahmin edilebilirlik: Hangi boyutun kullanılacağını öngörmek zor olabilir. Debugging zorluğu: Davranışları anlamak ilk başta kafa karıştırıcı. Modern Viewport Birimleri (2022+) CSS Spec'e yeni eklenen, mobile browser sorunlarını çözen birimler: svh, svw (Small Viewport) UI kontrolleri görünür olduğunda viewport boyutu. Mobile'da address bar açıkken olan boyut lvh, lvw (Large Viewport) UI kontrolleri gizli olduğunda viewport boyutu. Mobile'da address bar kapalıyken olan boyut dvh, dvw (Dynamic Viewport) UI kontrollerinin durumuna göre dinamik değişen boyut. En gerçekçi boyut, ama performans maliyeti var .hero { /* Klasik yaklaşım - mobile'da sorunlu */ height: 100vh; /* Modern yaklaşım - mobile browser bar'ları hesaba katar */ height: 100dvh; /* Fallback stratejisi */ height: 100vh; height: 100dvh; /* Destekleyen tarayıcılarda geçerli olur */ } .fixed-header { /* Small viewport - UI her zaman görünür */ height: 10svh; } .content-area { /* Large viewport - maksimum alan */ min-height: 100lvh; } Browser Desteği Sorunu: Nisan 2023 itibariyle major tarayıcılarda destek var Eski tarayıcılar için fallback şart /* Progressive Enhancement */ .section { height: 600px; /* Fallback */ height: 100vh; /* Eski tarayıcılar */ height: 100dvh; /* Modern tarayıcılar */ } Genel Olumsuz Yönler ve Dikkat Edilmesi Gerekenler 1. Accessibility Sorunları /* ❌ Kötü - kullanıcı zoom yaptığında okunaksız */ body { font-size: 1.5vw; } /* ✅ İyi - minimum ve maksimum değerler */ body { font-size: clamp(16px, 1.5vw, 24px); } Viewport birimleriyle font-size kullanırken kullanıcı tarayıcıda zoom yaptığında metin boyutu değişmez (px gibi sabit kalır). Bu WCAG accessibility kurallarını ihlal eder. 2. Performans Sorunları Viewport birimleri sürekli yeniden hesaplanır: Window resize'da Scroll'da (özellikle mobile'da address bar) Orientation change'de /* Dikkatli kullanım */ .element { /* Her scroll'da repaint tetikler */ transform: translateY(calc(50vh - 50%)); } 3. Print Media Sorunları /* Print'te viewport birimleri belirsiz davranır */ @media print { .hero { height: 100vh; /* Kağıt boyutunu mu, ekran boyutunu mu alır? */ height: auto; /* Daha güvenli */ } } 4. Container Query ile Çakışma /* Viewport vs Container - hangisi kullanılmalı? */ .card { /* Viewport'a göre - tüm ekrana göre ayarlanır */ padding: 2vw; /* Container'a göre - parent'a göre ayarlanır (modern) */ padding: 2cqw; } Modern yaklaşımda container query birimleri (cqw, cqh) daha mantıklı olabilir. 5. Hesaplama Karmaşıklığı /* Karmaşık ve debug edilmesi zor */ .element { width: calc(100vw - 20px); margin-left: calc(-50vw + 50%); padding: calc(2vmin + 1rem); } Best Practices Güvenli Kullanım Örnekleri: /* 1. Fluid Typography - clamp ile */ h1 { font-size: clamp(1.5rem, 5vw, 3rem); } /* 2. Full-width sections - overflow kontrolü ile */ .full-width { width: 100%; max-width: 100vw; margin-left: calc(-50vw + 50%); margin-right: calc(-50vw + 50%); } /* 3. Hero sections - fallback ile */ .hero { min-height: 600px; /* Fallback */ min-height: 100vh; /* Standart */ min-height: 100dvh; /* Modern */ } /* 4. Responsive spacing - rem ile kombinasyon */ .section { padding: clamp(2rem, 5vw, 6rem); } /* 5. Aspect ratio control - vmin ile */ .video-container { width: 80vmin; height: 45vmin; /* 16:9 aspect ratio her durumda */ } Kaçınılması Gerekenler: /* ❌ Kesinlikle yapma */ * { font-size: 2vw; /* Accessibility felaketi */ } /* ❌ Scrollbar sorunları */ body { width: 100vw; /* Yatay scroll oluşturur */ } /* ❌ Mobile keyboard sorunu */ .modal { height: 100vh; /* Keyboard açıldığında kesilir */ } /* ❌ Aşırı karmaşık hesaplamalar */ .element { width: calc(100vw - (100vw - 100%) - 2rem); } Özet Viewport birimleri güçlü araçlar ama: Mobile browser davranışlarını iyi bilmek şart Her zaman fallback değerler kullanın Accessibility'yi göz ardı etmeyin (clamp kullanın) Modern dvh, svh, lvh birimlerini öğrenin Performans etkilerini düşünün Container query birimlerini de değerlendirin Doğru kullanıldığında viewport birimleri gerçekten responsive ve fluid tasarımlar oluşturmanıza olanak sağlar, ama tuzaklarını bilmek kritik.
-
Heading(h1,h2,h3,h4,h5,h6) elementlerini sayfamızda kullanırken CSS'de stil uygularız. Bu uygulanan stillerin ne olduğunu bilmek için tarayıcının h1 elementine default olarak uyguladığı stilleri bilmek gerektirir. Çünkü başlangıç noktamız tarayıcı stilleridir. 1. Browser User Agent Stylesheet (Tarayıcı Varsayılan Stilleri) Chrome/WebKit Default Styles /* Chrome'un h1 için varsayılan stilleri */ h1 { display: block; font-size: 2em; margin-block-start: 0.67em; margin-block-end: 0.67em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold; } Tarayıcıların İç İçe h1 Mantığı /* 1 seviye iç içe (article > h1) */ :-webkit-any(article,aside,nav,section) h1 { font-size: 1.5em; margin-block-start: 0.83em; margin-block-end: 0.83em; } /* 2 seviye iç içe (article > section > h1) */ :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 { font-size: 1.17em; margin-block-start: 1em; margin-block-end: 1em; } /* 3 seviye iç içe */ :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 { font-size: 1em; /* Normal metin boyutu! */ margin-block-start: 1.33em; margin-block-end: 1.33em; } /* 4 seviye iç içe */ :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 { font-size: 0.83em; /* h1, h5'ten küçük! */ margin-block-start: 1.67em; margin-block-end: 1.67em; } /* 5 seviye iç içe */ :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) :-webkit-any(article,aside,nav,section) h1 { font-size: 0.67em; /* h1, h6'dan küçük! */ margin-block-start: 2.33em; margin-block-end: 2.33em; } Tüm Başlık Seviyelerinin Varsayılan Boyutları h1 { font-size: 2em; margin: 0.67em 0; } /* 32px */ h2 { font-size: 1.5em; margin: 0.83em 0; } /* 24px */ h3 { font-size: 1.17em; margin: 1em 0; } /* 18.72px */ h4 { font-size: 1em; margin: 1.33em 0; } /* 16px */ h5 { font-size: 0.83em; margin: 1.67em 0; } /* 13.28px */ h6 { font-size: 0.67em; margin: 2.33em 0; } /* 10.72px */ 2. HTML5 Outline Algorithm'ın Hikayesi HTML5'in Vaat Ettiği (Ama Gerçekleşmeyen) HTML5 şunu söyledi: "Her semantic section kendi başlık hiyerarşisine sahip olabilir!" <!-- HTML5'in hayali --> <body> <h1>Site Başlığı</h1> <article> <h1>Makale Başlığı</h1> <!-- Tarayıcı bunu h2 gibi ele alsın --> <section> <h1>Bölüm Başlığı</h1> <!-- Tarayıcı bunu h3 gibi ele alsın --> </section> </article> <aside> <h1>Sidebar Başlığı</h1> <!-- Tarayıcı bunu h2 gibi ele alsın --> </aside> </body> Problem: ❌ Hiçbir tarayıcı bu algoritma tam olarak uygulamadı ❌ Ekran okuyucular bu yapıyı doğru anlamıyor ❌ SEO açısından kafa karıştırıcı ❌ W3C 2022'de resmi olarak vazgeçti Gerçekte Ne Oldu? Tarayıcılar sadece görsel olarak küçülttüler, ama semantik olarak değiştirmediler: <article> <section> <h1>Bu başlık</h1> </section> </article> <!-- Ekran okuyucular bunu şöyle görür: --> <!-- "Heading level 1: Bu başlık" --> <!-- (h2 değil, h1 olarak!) --> 3. Modern CSS Yaklaşımları ❌ Yapılmaması Gerekenler <!-- KÖTÜ: İç içe h1 kullanımı --> <article> <h1>Ana Başlık</h1> <section> <h1>Alt Başlık</h1> <!-- Tarayıcı küçültür ama semantik yanlış --> </section> </article> <!-- KÖTÜ: Sadece görsel için h1 --> <div class="hero"> <h1>Hoş Geldiniz</h1> <!-- Sayfa başlığı değilse h1 olmamalı --> </div> ✅ Modern Doğru Yaklaşım <!-- İYİ: Doğru semantik hiyerarşi --> <article> <h1>Makale Başlığı</h1> <section> <h2>Bölüm Başlığı</h2> <h3>Alt Bölüm</h3> <h4>Detay</h4> </section> </article> Modern CSS Reset/Normalize /* Modern CSS Reset Yaklaşımı */ /* 1. Tarayıcı varsayılanlarını sıfırla */ h1, h2, h3, h4, h5, h6 { margin: 0; font-size: inherit; /* Parent'tan al */ font-weight: inherit; line-height: inherit; } /* 2. Kendi design system'ini kur */ :root { /* Typographic Scale (Major Third - 1.250) */ --font-size-base: 1rem; /* 16px */ --font-size-lg: 1.25rem; /* 20px */ --font-size-xl: 1.563rem; /* 25px */ --font-size-2xl: 1.953rem; /* 31px */ --font-size-3xl: 2.441rem; /* 39px */ --font-size-4xl: 3.052rem; /* 49px */ /* Spacing Scale */ --space-xs: 0.5rem; --space-sm: 1rem; --space-md: 1.5rem; --space-lg: 2rem; --space-xl: 3rem; /* Line Heights */ --line-height-tight: 1.2; --line-height-normal: 1.5; --line-height-loose: 1.8; } /* 3. Semantic heading styles */ h1 { font-size: var(--font-size-4xl); font-weight: 700; line-height: var(--line-height-tight); margin-block-end: var(--space-lg); letter-spacing: -0.02em; /* Optik düzeltme */ } h2 { font-size: var(--font-size-3xl); font-weight: 700; line-height: var(--line-height-tight); margin-block-start: var(--space-xl); margin-block-end: var(--space-md); } h3 { font-size: var(--font-size-2xl); font-weight: 600; line-height: var(--line-height-tight); margin-block-start: var(--space-lg); margin-block-end: var(--space-sm); } h4 { font-size: var(--font-size-xl); font-weight: 600; line-height: var(--line-height-normal); margin-block-start: var(--space-md); margin-block-end: var(--space-sm); } h5 { font-size: var(--font-size-lg); font-weight: 600; line-height: var(--line-height-normal); margin-block-start: var(--space-md); margin-block-end: var(--space-xs); } h6 { font-size: var(--font-size-base); font-weight: 600; line-height: var(--line-height-normal); margin-block-start: var(--space-sm); margin-block-end: var(--space-xs); text-transform: uppercase; letter-spacing: 0.05em; } 4. Utility-First Yaklaşım (Tailwind tarzı) <!-- Semantic HTML + Utility Classes --> <article> <h1 class="text-5xl font-bold leading-tight mb-8"> Ana Başlık </h1> <h2 class="text-3xl font-semibold leading-snug mt-12 mb-6"> Alt Başlık </h2> <h3 class="text-2xl font-medium leading-normal mt-8 mb-4"> Bölüm Başlığı </h3> </article> /* Custom utility system */ .text-5xl { font-size: 3rem; } .text-3xl { font-size: 1.875rem; } .text-2xl { font-size: 1.5rem; } .font-bold { font-weight: 700; } .font-semibold { font-weight: 600; } .font-medium { font-weight: 500; } .leading-tight { line-height: 1.2; } .leading-snug { line-height: 1.375; } .leading-normal { line-height: 1.5; } 5. Component-Based Yaklaşım /* Semantic başlıklar + görsel class'lar ayırımı */ /* Semantic HTML her zaman doğru */ <article> <h1 class="display-1">Görsel Başlık</h1> <h2 class="title-large">Alt Başlık</h2> </article> <section> <h2 class="display-2">Büyük Başlık (ama h2)</h2> <h3 class="body-large">Küçük Başlık (ama h3)</h3> </section> /* CSS */ .display-1 { font-size: clamp(2.5rem, 5vw + 1rem, 4rem); font-weight: 800; line-height: 1.1; letter-spacing: -0.02em; } .display-2 { font-size: clamp(2rem, 4vw + 1rem, 3rem); font-weight: 700; line-height: 1.2; } .title-large { font-size: clamp(1.5rem, 3vw + 0.5rem, 2rem); font-weight: 600; line-height: 1.3; } .body-large { font-size: 1.25rem; font-weight: 500; line-height: 1.5; } 6. Responsive Typography /* Modern fluid typography */ h1 { /* min: 32px, max: 64px, viewport-based scaling */ font-size: clamp(2rem, 4vw + 1rem, 4rem); /* Container query ile responsive */ font-size: clamp(2rem, 8cqi, 4rem); line-height: 1.1; margin-block-end: clamp(1rem, 3vw, 2rem); } /* Breakpoint-based (geleneksel) */ h1 { font-size: 2rem; /* 32px - mobile */ } @media (min-width: 640px) { h1 { font-size: 2.5rem; /* 40px - tablet */ } } @media (min-width: 1024px) { h1 { font-size: 3rem; /* 48px - desktop */ } } @media (min-width: 1280px) { h1 { font-size: 4rem; /* 64px - large desktop */ } } 7. Modern Best Practices Özet /* Tam Modern H1 Implementasyonu */ /* 1. Reset browser defaults */ h1 { margin: 0; font-size: inherit; font-weight: inherit; } /* 2. Override nested sectioning bugs */ article h1, aside h1, nav h1, section h1 { font-size: inherit; /* Parent'tan al, tarayıcı küçültmesin */ } /* 3. Custom design system */ h1 { /* Responsive fluid sizing */ font-size: clamp(2rem, 5vw + 1rem, 4rem); /* Typography */ font-weight: 700; line-height: 1.1; letter-spacing: -0.02em; /* Spacing with logical properties */ margin-block-end: clamp(1rem, 3vw, 2rem); /* Color with custom properties */ color: var(--color-heading, hsl(0 0% 10%)); /* Text wrapping */ text-wrap: balance; /* Modern tarayıcılarda */ max-inline-size: 20ch; /* Optimal başlık genişliği */ } /* 4. Context variants */ .hero h1 { font-size: clamp(3rem, 8vw + 1rem, 6rem); text-align: center; } .article h1 { font-size: clamp(2rem, 4vw + 1rem, 3rem); } .card h1 { font-size: 1.5rem; } /* 5. Dark mode */ @media (prefers-color-scheme: dark) { h1 { color: var(--color-heading-dark, hsl(0 0% 95%)); } } 8. Gerçek Dünya Örneği <!DOCTYPE html> <html lang="tr"> <head> <style> /* Modern H1 Implementation */ * { margin: 0; padding: 0; box-sizing: border-box; } :root { --color-text: hsl(0 0% 10%); --color-bg: hsl(0 0% 98%); --font-base: system-ui, -apple-system, sans-serif; } body { font-family: var(--font-base); color: var(--color-text); background: var(--color-bg); line-height: 1.6; padding: 2rem; } /* h1 reset - tarayıcı otomatik küçültmesini engelle */ h1 { font-size: inherit; font-weight: inherit; margin: 0; } /* Semantic yapı */ .page-title { font-size: clamp(2.5rem, 6vw + 1rem, 4.5rem); font-weight: 800; line-height: 1.1; letter-spacing: -0.03em; margin-block-end: 1.5rem; text-wrap: balance; } .section-title { font-size: clamp(1.75rem, 4vw + 0.5rem, 3rem); font-weight: 700; line-height: 1.2; margin-block-start: 3rem; margin-block-end: 1rem; } .card-title { font-size: 1.5rem; font-weight: 600; line-height: 1.3; margin-block-end: 0.5rem; } article { max-width: 70ch; } section { margin-block: 2rem; } </style> </head> <body> <article> <!-- Sayfa ana başlığı --> <h1 class="page-title">Modern H1 Kullanımı</h1> <section> <!-- Alt bölüm başlığı --> <h2 class="section-title">İlk Bölüm</h2> <p>İçerik...</p> <div class="card"> <!-- Kart başlığı --> <h3 class="card-title">Kart Başlığı</h3> <p>Kart içeriği...</p> </div> </section> </article> </body> </html> 9. Kritik Kurallar ✅ YAP: Her sayfada sadece bir h1 kullan Başlık hiyerarşisini atlamadan ilerle (h1 → h2 → h3) Semantic HTML kullan, görsel için class kullan clamp() ile fluid typography uygula Logical properties kullan (margin-block, margin-inline) ❌ YAPMA: İç içe section'larda h1 tekrarlama h1'den h3'e atlama (h2'yi atlayarak) Sadece görsel için h1 kullanma Tarayıcının otomatik küçültmesine güvenme Fixed pixel değerleri kullanma Sonuç: Tarayıcının varsayılan h1 davranışı karmaşık ve artık kullanılmıyor. Modern yaklaşım: doğru semantic HTML + custom CSS design system + fluid typography + accessibility!
-
Relative units, bir öğenin boyutunu başka bir değere göre belirleyen birimlerdir. Sabit (absolute) birimlerden farklı olarak, responsive tasarım için çok daha uygun ve esnek çözümler sunarlar. Ana Relative Units rem (root em) Root element'in (html) font-size'ına göre hesaplanır 1rem = html'in font-size değeri (genelde 16px) En çok kullanılan ve önerilen birim html { font-size: 16px; /* 1rem = 16px */ } .container { padding: 2rem; /* 32px */ margin-bottom: 1.5rem; /* 24px */ } em Parent element'in font-size'ına göre hesaplanır İç içe kullanımlarda kümülatif etki yapar Daha spesifik durumlarda kullanılır .parent { font-size: 20px; } .child { padding: 1em; /* 20px (parent'ın font-size'ı) */ font-size: 0.8em; /* 16px */ } % (percentage) Parent element'in ilgili özelliğine göre hesaplanır Width/height için çok kullanışlı .container { width: 80%; /* Parent'ın genişliğinin %80'i */ } vw/vh (viewport units) vw: viewport width'in %1'i vh: viewport height'in %1'i 100vw = tam ekran genişliği .hero { height: 100vh; /* Tam ekran yüksekliği */ width: 100vw; /* Tam ekran genişliği */ } vmin/vmax vmin: viewport'un küçük boyutunun %1'i vmax: viewport'un büyük boyutunun %1'i ch "0" karakterinin genişliği Metin genişlikleri için kullanışlı p { max-width: 65ch; /* Okunabilir satır uzunluğu */ } Hangi Özellikte Hangisi Kullanılmalı? Font-size → rem h1 { font-size: 2.5rem; } p { font-size: 1rem; } small { font-size: 0.875rem; } ✅ Tutarlı ölçeklendirme ✅ Kullanıcı tercihlerine saygı Spacing (padding/margin) → rem .card { padding: 2rem; margin-bottom: 1.5rem; } ✅ Tutarlı aralıklar ✅ Global ölçeklendirme Width/max-width → % veya ch .container { width: 90%; /* veya */ max-width: 1200px; } p { max-width: 65ch; /* Okunabilirlik için */ } Height (full-screen) → vh .hero { height: 100vh; min-height: 500px; /* Fallback */ } Line-height → unitless number p { line-height: 1.6; /* Birim yok! */ } ✅ Font-size ile orantılı ölçeklenir Border-radius → px veya % .button { border-radius: 8px; /* Sabit yuvarlaklık */ } .circle { border-radius: 50%; /* Tam daire */ } Component içi ilişkiler → em .button { font-size: 1rem; padding: 0.5em 1em; /* Font-size'a göre */ border-radius: 0.25em; } ✅ Component kendi içinde ölçeklenebilir Örnek: /* Modern CSS Architecture */ :root { --spacing-xs: 0.5rem; --spacing-sm: 1rem; --spacing-md: 1.5rem; --spacing-lg: 2rem; --spacing-xl: 3rem; } html { font-size: 100%; /* Kullanıcı tercihlerine saygı */ } body { font-size: 1rem; line-height: 1.6; } /* Layout */ .container { width: 90%; max-width: 1200px; margin: 0 auto; padding: var(--spacing-md); } /* Typography */ h1 { font-size: 2.5rem; } h2 { font-size: 2rem; } h3 { font-size: 1.5rem; } p { font-size: 1rem; max-width: 65ch; } /* Components */ .button { font-size: 1rem; padding: 0.75em 1.5em; /* em kullanımı */ border-radius: 0.25em; } /* Full-screen */ .hero { min-height: 100vh; } Altın kural: Genel olarak rem kullan, component(button, card, navbar, modal vb..) içi ilişkiler için em, layout için % ve tam ekran için vh tercih et!
-
BEM (Block Element Modifier), Yandex tarafından geliştirilen bir CSS isimlendirme ve mimari metodolojisidir. Amacı, kodun okunabilir, yeniden kullanılabilir ve ölçeklenebilir olmasını sağlamaktır. BEM'in Üç Bileşeni 1. Block (Blok) Bağımsız, kendi başına anlamlı bir bileşendir. .card { } .menu { } .header { } .button { } .search-form { } Özellikler: Tekrar kullanılabilir Bağımsız çalışabilir İç içe yerleştirilebilir Kebab-case ile yazılır 2. Element (Eleman) Blokun bir parçasıdır, blok dışında bağımsız anlamı yoktur. İki alt çizgi (__) ile gösterilir. .card__header { } .card__body { } .card__footer { } .card__title { } .card__image { } .menu__item { } .menu__link { } .menu__icon { } Özellikler: Bloğun parçasıdır Blok olmadan kullanılamaz Sözdizimi: block__element 3. Modifier (Değiştirici) Blok veya elementin görünümünü, durumunu veya davranışını değiştirir. İki tire (--) ile gösterilir. /* Blok modifierleri */ .card--featured { } .card--dark { } .card--large { } /* Element modifierleri */ .card__title--bold { } .card__image--rounded { } /* Durum modifierleri */ .button--disabled { } .button--active { } .menu__item--selected { } Tam Yapı ve Kombinasyonlar /* Block */ .product-card { } /* Elements */ .product-card__image { } .product-card__title { } .product-card__description { } .product-card__price { } .product-card__button { } /* Block Modifiers */ .product-card--featured { } .product-card--sale { } .product-card--out-of-stock { } /* Element Modifiers */ .product-card__button--primary { } .product-card__button--disabled { } .product-card__price--discount { } HTML'de Kullanım: <!-- Basit kart --> <div class="product-card"> <img class="product-card__image" src="product.jpg" alt=""> <h3 class="product-card__title">Ürün Adı</h3> <p class="product-card__description">Ürün açıklaması</p> <span class="product-card__price">₺299</span> <button class="product-card__button">Sepete Ekle</button> </div> <!-- Öne çıkan kart (modifier ile) --> <div class="product-card product-card--featured"> <img class="product-card__image" src="product.jpg" alt=""> <h3 class="product-card__title">Ürün Adı</h3> <p class="product-card__description">Ürün açıklaması</p> <span class="product-card__price product-card__price--discount">₺199</span> <button class="product-card__button product-card__button--primary"> Hemen Al </button> </div> <!-- İndirimli kart --> <div class="product-card product-card--sale"> <img class="product-card__image" src="product.jpg" alt=""> <h3 class="product-card__title">Ürün Adı</h3> <p class="product-card__description">Ürün açıklaması</p> <span class="product-card__price product-card__price--discount">₺199</span> <button class="product-card__button">Sepete Ekle</button> </div> CSS Örneği /* Block */ .product-card { background: white; border-radius: 8px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); } /* Elements */ .product-card__image { width: 100%; height: 200px; object-fit: cover; border-radius: 4px; } .product-card__title { font-size: 1.5rem; margin: 15px 0 10px; color: #333; } .product-card__description { font-size: 0.9rem; color: #666; line-height: 1.5; } .product-card__price { display: block; font-size: 1.8rem; font-weight: bold; color: #2c3e50; margin: 15px 0; } .product-card__button { width: 100%; padding: 12px; border: none; background: #3498db; color: white; border-radius: 4px; cursor: pointer; font-size: 1rem; } /* Block Modifiers */ .product-card--featured { border: 3px solid #f39c12; box-shadow: 0 4px 16px rgba(243, 156, 18, 0.3); } .product-card--sale { position: relative; background: linear-gradient(135deg, #fff 0%, #fffaf0 100%); } .product-card--out-of-stock { opacity: 0.6; pointer-events: none; } /* Element Modifiers */ .product-card__price--discount { color: #e74c3c; } .product-card__button--primary { background: #27ae60; font-weight: bold; } .product-card__button--primary:hover { background: #229954; } .product-card__button--disabled { background: #95a5a6; cursor: not-allowed; } Önemli Kurallar ve İpuçları ❌ YANLIŞ Kullanımlar /* Element içinde element YAPMAYINIZ */ .card__header__title { } /* YANLIŞ */ /* Bunun yerine: */ .card__header { } .card__title { } /* Doğrudan block'a bağlı */ ✅ DOĞRU Kullanımlar /* İç içe elementler varsa düz yazın */ .modal { } .modal__header { } .modal__title { } /* modal__header__title değil */ .modal__close-button { } .modal__body { } .modal__footer { } Gerçek Dünya Örneği: Navigasyon Menüsü <nav class="main-nav main-nav--dark"> <div class="main-nav__logo"> <img class="main-nav__logo-image" src="logo.svg" alt="Logo"> </div> <ul class="main-nav__menu"> <li class="main-nav__item main-nav__item--active"> <a class="main-nav__link" href="#">Anasayfa</a> </li> <li class="main-nav__item"> <a class="main-nav__link" href="#">Hakkımızda</a> </li> <li class="main-nav__item main-nav__item--dropdown"> <a class="main-nav__link" href="#">Ürünler</a> <ul class="main-nav__submenu"> <li class="main-nav__subitem"> <a class="main-nav__sublink" href="#">Kategori 1</a> </li> </ul> </li> </ul> <button class="main-nav__button main-nav__button--search"> Ara </button> </nav> .main-nav { display: flex; align-items: center; padding: 20px; background: white; } .main-nav--dark { background: #2c3e50; color: white; } .main-nav__logo { margin-right: auto; } .main-nav__logo-image { height: 40px; } .main-nav__menu { display: flex; list-style: none; gap: 30px; margin: 0; padding: 0; } .main-nav__item { position: relative; } .main-nav__item--active .main-nav__link { font-weight: bold; border-bottom: 2px solid #3498db; } .main-nav__item--dropdown:hover .main-nav__submenu { display: block; } .main-nav__link { text-decoration: none; color: inherit; padding: 8px 0; display: inline-block; } .main-nav__submenu { display: none; position: absolute; top: 100%; left: 0; background: white; box-shadow: 0 4px 8px rgba(0,0,0,0.1); list-style: none; padding: 10px 0; min-width: 200px; } .main-nav__button { padding: 10px 20px; border: none; background: #3498db; color: white; border-radius: 4px; cursor: pointer; } .main-nav__button--search { margin-left: 20px; } BEM'in Avantajları Spesifiklik sorunları yok - Her sınıf tek başına Okunabilir - İsimden ne olduğu anlaşılıyor Yeniden kullanılabilir - Bloklar bağımsız Bakımı kolay - Değişiklikler izole Takım çalışması - Herkes aynı sistemi kullanır Ölçeklenebilir - Büyük projelerde kaos olmuyor Ne Zaman BEM Kullanmalı? ✅ Uygun: Büyük projeler Takım çalışması Bileşen tabanlı tasarım Uzun vadeli projeler ❌ Gerekli değil: Küçük landing page'ler Prototype'lar Tek sayfalık projeler BEM başta biraz karmaşık gelebilir, ama alıştıktan sonra CSS yazmayı çok daha organize ve keyifli hale getirir!
-
PHP 8+ ile birlikte gelen modern özelliklerle encapsulation (kapsülleme) prensibini derinlemesine inceleyelim. Temel Kavram: Neden Private? Verileri gizleyip davranışı ortaya çıkarmanın amacı: Değişimin kontrolü: Dışarıdan doğrudan erişimi engelleyerek değişiklikleri kontrol edersiniz İç implementasyon özgürlüğü: İç yapıyı değiştirdiğinizde dış kodlar etkilenmez Veri tutarlılığı: Validation ve business logic'i merkezi bir noktada yönetirsiniz PHP 8.0+ Constructor Property Promotion PHP 8.0'ın getirdiği en önemli özelliklerden biri: <?php // ❌ Eski yöntem (PHP 7.x) class User { private string $name; private string $email; private int $age; public function __construct(string $name, string $email, int $age) { $this->name = $name; $this->email = $email; $this->age = $age; } } // ✅ Yeni yöntem (PHP 8.0+) class User { public function __construct( private string $name, private string $email, private int $age ) {} // Getter'lar ile davranış ortaya çıkarma public function getName(): string { return $this->name; } public function getEmail(): string { return $this->email; } public function getAge(): int { return $this->age; } // Kontrollü değişim public function updateEmail(string $newEmail): void { if (!filter_var($newEmail, FILTER_VALIDATE_EMAIL)) { throw new InvalidArgumentException('Geçersiz email formatı'); } $this->email = $newEmail; } public function celebrateBirthday(): void { $this->age++; } } PHP 8.1+ Readonly Properties PHP 8.1 ile gelen readonly özelliği immutability sağlar: <?php class Product { public function __construct( private readonly string $id, private readonly string $name, private float $price, private readonly DateTime $createdAt ) {} // ID ve name değiştirilemez (readonly) public function getId(): string { return $this->id; } public function getName(): string { return $this->name; } // Fiyat değiştirilebilir ama kontrollü public function getPrice(): float { return $this->price; } public function applyDiscount(float $percentage): void { if ($percentage < 0 || $percentage > 100) { throw new InvalidArgumentException('İndirim 0-100 arasında olmalı'); } $this->price = $this->price * (1 - $percentage / 100); } public function getCreatedAt(): DateTime { // ⚠️ DateTime mutable bir object, clone ile koruma return clone $this->createdAt; } } $product = new Product('P001', 'Laptop', 15000.0, new DateTime()); echo $product->getPrice(); // 15000 $product->applyDiscount(20); // %20 indirim echo $product->getPrice(); // 12000 // $product->id = 'P002'; // ❌ HATA: Readonly property PHP 8.2+ Readonly Classes Tüm class'ı immutable yapmak için: <?php readonly class Money { public function __construct( public float $amount, public string $currency ) {} // Yeni bir Money objesi döndürerek değişimi yönetme public function add(Money $other): self { if ($this->currency !== $other->currency) { throw new InvalidArgumentException('Para birimleri eşleşmiyor'); } return new self( $this->amount + $other->amount, $this->currency ); } public function multiply(float $factor): self { return new self( $this->amount * $factor, $this->currency ); } public function format(): string { return number_format($this->amount, 2) . ' ' . $this->currency; } } $price = new Money(100, 'TRY'); $tax = new Money(18, 'TRY'); $total = $price->add($tax); echo $total->format(); // 118.00 TRY // $price->amount = 200; // ❌ HATA: Readonly property Pratik Örnek: E-Ticaret Sepet Sistemi <?php readonly class CartItem { public function __construct( public string $productId, public string $productName, public float $unitPrice, public int $quantity ) { if ($quantity <= 0) { throw new InvalidArgumentException('Miktar pozitif olmalı'); } } public function getTotalPrice(): float { return $this->unitPrice * $this->quantity; } public function changeQuantity(int $newQuantity): self { return new self( $this->productId, $this->productName, $this->unitPrice, $newQuantity ); } } class ShoppingCart { /** @var array<string, CartItem> */ private array $items = []; public function addItem(CartItem $item): void { $productId = $item->productId; if (isset($this->items[$productId])) { $existingItem = $this->items[$productId]; $newQuantity = $existingItem->quantity + $item->quantity; $this->items[$productId] = $existingItem->changeQuantity($newQuantity); } else { $this->items[$productId] = $item; } } public function removeItem(string $productId): void { unset($this->items[$productId]); } public function updateQuantity(string $productId, int $quantity): void { if (!isset($this->items[$productId])) { throw new InvalidArgumentException('Ürün sepette bulunamadı'); } if ($quantity <= 0) { $this->removeItem($productId); } else { $this->items[$productId] = $this->items[$productId] ->changeQuantity($quantity); } } /** @return array<CartItem> */ public function getItems(): array { return array_values($this->items); } public function getTotalAmount(): float { return array_reduce( $this->items, fn($total, $item) => $total + $item->getTotalPrice(), 0.0 ); } public function getItemCount(): int { return array_reduce( $this->items, fn($total, $item) => $total + $item->quantity, 0 ); } public function clear(): void { $this->items = []; } } // Kullanım $cart = new ShoppingCart(); $laptop = new CartItem('P001', 'Laptop', 15000, 1); $mouse = new CartItem('P002', 'Mouse', 250, 2); $cart->addItem($laptop); $cart->addItem($mouse); echo "Toplam ürün: " . $cart->getItemCount() . "\n"; // 3 echo "Toplam tutar: " . $cart->getTotalAmount() . " TRY\n"; // 15500 TRY $cart->updateQuantity('P002', 5); echo "Güncel tutar: " . $cart->getTotalAmount() . " TRY\n"; // 16250 TRY // ❌ Dışarıdan doğrudan erişim yok // $cart->items['P001']->quantity = 10; // Private property Özet PHP 8+ ile encapsulation'ı uygulamak için: Constructor Property Promotion kullanın (PHP 8.0+) Readonly properties ile immutability sağlayın (PHP 8.1+) Readonly classes ile tam immutable objeler oluşturun (PHP 8.2+) Getter/Setter yerine davranışı ortaya çıkaran metodlar yazın Validation logic'i her zaman içeride tutun Return type declarations ile tip güvenliği sağlayın Bu yaklaşım sayesinde kodunuz daha güvenli, test edilebilir ve sürdürülebilir olur! PHP 8+ ile "tüm özellikleri private yapmak" şu anlama gelir: Varsayılan: Veriyi private yap, davranışı public metotla aç. Daha Kolay: private özellikleri Constructor Property Promotion ile hızlıca tanımla. Daha Güvenli (Durum): string veya int gibi ilkel tipler yerine private Enum kullanarak iş kurallarını tipe dönüştür. En Güvenli (Değişmezlik): Asla değişmemesi gereken veriler için private readonly kullanarak nesnenin temelini kilitle.
-
STYLE LEAK NEDİR? Style Leak (Stil Sızıntısı), bir componentin veya modülün CSS stil kurallarının, olmaması gereken yerlere sızması ve istenmeyen elementleri etkilemesidir. TEMEL PROBLEM <!-- Component 1: Card --> <div class="card"> <h2>Başlık</h2> <p>İçerik</p> </div> <!-- Component 2: Sidebar --> <div class="sidebar"> <h2>Sidebar Başlığı</h2> <p>Sidebar içeriği</p> </div> /* Card component CSS'i */ .card h2 { color: blue; font-size: 24px; } .card p { color: gray; } Problem yok gibi görünüyor, ama... <!-- Şimdi card içinde sidebar kullanırsak: --> <div class="card"> <h2>Card Başlık</h2> <div class="sidebar"> <h2>Sidebar Başlık</h2> <!-- 🔥 LEAK! Card'ın h2 stili burayı da etkiliyor --> <p>İçerik</p> <!-- 🔥 LEAK! --> </div> </div> .card h2 selector'ü, card içindeki TÜM h2'leri etkiler - sidebar'ınkini de! STYLE LEAK TÜRLERİ 1. DESCENDANT SELECTOR LEAK (En Yaygın) /* ❌ Leak riski YÜKSEk */ .header a { color: white; text-decoration: none; } <header class="header"> <nav> <a href="/">Ana Sayfa</a> </nav> <!-- Başka bir component buraya gelirse... --> <div class="search-box"> <a href="/advanced">Gelişmiş Arama</a> <!-- 🔥 LEAK! --> </div> </header> 2. GLOBAL SELECTOR LEAK /* ❌ ÇOK TEHLİKELİ */ h1 { color: blue; font-size: 32px; } p { line-height: 1.8; } Bu tüm sayfadaki TÜM h1 ve p'leri etkiler! 3. CHILD SELECTOR LEAK /* ✓ Biraz daha güvenli ama yine de leak olabilir */ .container > div { padding: 20px; } <div class="container"> <div>OK - Etkilenir</div> <section> <div>Etkilenmez (torun)</div> </section> <!-- Ama yeni bir component eklenirse... --> <div class="special-component"> <!-- 🔥 Bu div de etkilenir! --> </div> </div> 4. ELEMENT + CLASS COMBINATION LEAK /* ❌ Specificity yüksek ama yine leak olabilir */ div.box { background: white; } 5. UNIVERSAL SELECTOR LEAK /* ❌ EN BÜYÜK LEAK! */ * { box-sizing: border-box; } .container * { margin: 0; /* Container içindeki HER ŞEY etkilenir */ } LEAK NASIL OLUŞUR? Senaryo 1: Component İçinde Component /* Navbar component */ .navbar button { background: blue; color: white; } <nav class="navbar"> <button>Ana Menü</button> <!-- Dropdown component ekliyoruz --> <div class="dropdown"> <button>Dropdown</button> <!-- 🔥 Mavi oldu! --> </div> </nav> Senaryo 2: Third-party Component /* Senin CSS'in */ .modal p { font-size: 14px; color: gray; } <div class="modal"> <p>Modal içeriği</p> <!-- React Date Picker gibi 3rd party component --> <DatePicker> <!-- İçinde p elementleri var --> <p>Tarih seç</p> <!-- 🔥 Senin stilinle bozuldu! --> </DatePicker> </div> Senaryo 3: Dynamic Content .article img { border-radius: 8px; max-width: 100%; } <article class="article"> <img src="main.jpg" alt="Ana resim"> <!-- Kullanıcı bir yorum widget'ı ekliyor --> <div class="comments-widget"> <img src="avatar.jpg"> <!-- 🔥 Yuvarlak köşe oldu! --> </div> </article> LEAK ÖNLEME STRATEJİLERİ 1. DIRECT CHILD SELECTOR (>) /* ❌ Leak riski */ .card p { color: gray; } /* ✓ Daha güvenli */ .card > p { color: gray; } /* ✓ En güvenli */ .card > .card-content > p { color: gray; } Altın Kural: Selector'lerinizi mümkün olduğunca spesifik ve sığ tutun. Generic element selector'lerden kaçının!
-
Bir CSS Rule (kural), bir veya daha fazla HTML elementine stil vermek için yazılan tam bir CSS ifadesidir. ANATOMY (Anatomisi) selector { property: value; } Detaylı Anatomi: /* ┌─ SELECTOR (Seçici) │ ▼ */ h1 { /* ← Opening brace (Açılış süslü parantezi) */ color: blue; /* ← Declaration (Bildirim) */ font-size: 24px; /* ← Başka bir declaration */ } /* ← Closing brace (Kapanış süslü parantezi) */ Bileşenler: selector { property: value; │ │ │ └─ VALUE (Değer) └─ PROPERTY (Özellik) └──────────┘ DECLARATION (Bildirim) } └──────────────────────┘ DECLARATION BLOCK (Bildirim Bloğu) └──────────────────────────┘ COMPLETE CSS RULE (Tam CSS Kuralı) TERMİNOLOJİ 1. CSS RULE (Tüm yapı) h1 { color: blue; } Tüm bu yapıya "CSS Rule" denir. 2. SELECTOR (Seçici) h1 ← Selector Hangi element(ler)e stil uygulanacağını belirler. 3. DECLARATION BLOCK (Bildirim Bloğu) { color: blue; font-size: 24px; } Süslü parantezler içindeki tüm bildirimler. 4. DECLARATION (Bildirim) color: blue; Tek bir özellik-değer çifti + noktalı virgül. 5. PROPERTY (Özellik) color ← Property Değiştirmek istediğin stil özelliği. 6. VALUE (Değer) blue ← Value Özelliğe atadığın değer. FARKLI CSS RULE TİPLERİ 1. Style Rule (En yaygın) p { color: red; margin: 10px; } 2. At-Rule (@ ile başlayan) @media (max-width: 768px) { body { font-size: 14px; } } @import url('styles.css'); @keyframes slideIn { from { transform: translateX(-100%); } to { transform: translateX(0); } } @font-face { font-family: 'MyFont'; src: url('font.woff2'); } RULE vs DECLARATION vs STATEMENT Karşılaştırma: /* STATEMENT (İfade) - En genel terim */ @import url('base.css'); /* At-rule statement */ p { color: blue; } /* Style rule statement */ /* RULE (Kural) */ h1 { font-size: 32px; } /* ← Bu bir rule */ /* DECLARATION (Bildirim) */ color: red; /* ← Bu bir declaration */ font-size: 16px; /* ← Bu da bir declaration */ ÇOKLU SEÇİCİLERLE RULE /* Tek bir rule, birden fazla selector */ h1, h2, h3 { font-family: Arial; color: navy; } /* Bu şuna eşittir: */ h1 { font-family: Arial; color: navy; } h2 { font-family: Arial; color: navy; } h3 { font-family: Arial; color: navy; } NESTED RULES (Modern CSS) .card { padding: 20px; /* İç içe rule */ h2 { color: blue; } p { margin: 10px 0; } } /* Derlendiğinde: */ .card { padding: 20px; } .card h2 { color: blue; } .card p { margin: 10px 0; } CONDITIONAL RULES /* Media Query içinde rules */ @media (min-width: 768px) { .container { /* ← Bu bir rule */ max-width: 1200px; } .sidebar { /* ← Bu da ayrı bir rule */ width: 300px; } } /* Container Query */ @container (min-width: 400px) { .card { /* ← Rule */ display: grid; } } /* Supports Query */ @supports (display: grid) { .layout { /* ← Rule */ display: grid; } } SCOPE İLE RULES /* Modern CSS Scoping */ @scope (.card) { h2 { /* ← Bu rule sadece .card içinde geçerli */ color: blue; } p { /* ← Bu da */ margin: 0; } } INVALID RULES (Geçersiz Kurallar) Sözdizimi Hataları: /* ❌ Noktalı virgül eksik */ p { color: red font-size: 16px; } /* ❌ İki nokta eksik */ p { color red; } /* ❌ Süslü parantez eksik */ p { color: red; /* ❌ Geçersiz property */ p { collor: red; /* typo */ } /* ❌ Geçersiz value */ p { color: bluee; /* typo */ } Browser Davranışı: p { color: red; font-sizeee: 16px; /* ❌ Geçersiz - ignore edilir */ margin: 10px; /* ✓ Bu hala çalışır */ } DECLARATION'DA ÖZEL DURUMLAR Shorthand Properties .box { /* Tek bir declaration, 4 değer */ margin: 10px 20px 10px 20px; /* Aynı şeyin longhand hali - 4 ayrı declaration */ margin-top: 10px; margin-right: 20px; margin-bottom: 10px; margin-left: 20px; } Multiple Values .element { /* Tek declaration, virgülle ayrılmış değerler */ font-family: Arial, Helvetica, sans-serif; /* Tek declaration, boşlukla ayrılmış değerler */ box-shadow: 0 2px 4px rgba(0,0,0,0.1); /* Tek declaration, birden fazla background */ background: linear-gradient(red, blue), url('pattern.png'); } Custom Properties: .element { /* Declaration: custom property tanımlama */ --main-color: blue; --spacing: 20px; /* Declaration: custom property kullanma */ color: var(--main-color); padding: var(--spacing); } IMPORTANT DECLARATION: .element { color: red !important; /* ^^^^^^^^^^ Bu declaration'ın bir parçası */ } !important declaration'ın değerinin bir parçasıdır, ayrı bir şey değil. RULE SPECIFICITY Her rule'un bir specificity'si vardır: /* Specificity: 1 */ p { color: black; } /* Specificity: 10 */ .text { color: blue; } /* Specificity: 100 */ #main { color: red; } /* Specificity: 111 */ #main p.text { color: green; } Aynı elemente birden fazla rule uygulandığında, en yüksek specificity'li rule kazanır. COMPUTING A RULE Browser'ın bir rule'u nasıl işlediği: .parent { font-size: 20px; } .child { font-size: 1.5em; } ``` ``` 1. Parse CSS → Rule'u anla 2. Match selector → .child elementlerini bul 3. Apply declarations → Her declaration'ı uygula: - font-size: 1.5em - Parent'ın computed value: 20px - Computed value: 30px (20 × 1.5) 4. Paint → Ekrana çiz Terimler: Rule: Tüm yapı (selector + declarations) Selector: Hangi elementler Declaration: property: value çifti Property: Değiştirilen özellik Value: Atanan değer Declaration Block: Tüm declarations ({ ... }) At-Rules: @ ile başlayan özel kurallar (@media, @import, @keyframes, vb.)
-
1. INHERITANCE NEDİR? Inheritance (Kalıtım), bazı CSS özelliklerinin parent elementlerden child elementlere otomatik olarak geçmesidir. <div style="color: blue; border: 1px solid red;"> <p>Bu metin mavi olur</p> <span>Bu da mavi olur</span> </div> color: blue → Miras alınır (inherit edilir) border: 1px solid red → Miras alınmaz 2. HANGİ ÖZELLİKLER MIRAS ALINIR? Miras Alınan Özellikler (Inherited Properties) Tipografi/Metin Özellikleri: color font-family font-size font-style font-variant font-weight font letter-spacing line-height text-align text-indent text-transform white-space word-spacing direction Liste Özellikleri: list-style list-style-image list-style-position list-style-type Tablo Özellikleri: border-collapse border-spacing caption-side empty-cells Diğer: cursor visibility (kısmen) quotes orphans widows Miras Alınmayan Özellikler (Non-Inherited) Box Model: margin padding border width height max-width min-height /* vb. */ Positioning: position top, right, bottom, left z-index float clear Background: background background-color background-image background-position /* vb. */ Display: display overflow opacity Transform & Animation: transform transition animation 3. INHERITANCE NASIL ÇALIŞIR? Doğal Kalıtım <style> body { font-family: Arial; color: #333; line-height: 1.6; } </style> <body> <div> <p>Bu metin Arial, #333 renk, 1.6 line-height</p> <span>Bu da aynı özellikleri alır</span> </div> </body> Kalıtım Zinciri <style> .grandparent { color: red; font-size: 20px; } .parent { font-size: 16px; /* Override eder */ /* color hala red */ } </style> <div class="grandparent"> <div class="parent"> <p>Metin: red renk, 16px boyut</p> </div> </div> 4. INHERITANCE KONTROL DEĞERLERİ inherit /* Zorla parent'tan miras al */ .child { border: inherit; /* Normal şartlarda miras alınmaz */ } <style> .parent { border: 2px solid blue; } .child { border: inherit; /* Parent'ın border'ını alır */ } </style> <div class="parent"> <div class="child">Mavi border alır</div> </div> initial: /* Özelliği başlangıç değerine döndür */ .element { color: initial; /* Browser'ın default değeri (genelde black) */ } .parent { color: red; } .child { color: initial; /* red değil, black olur */ } unset /* Eğer inherit edilebilir ise inherit, değilse initial */ .element { color: unset; /* inherit gibi davranır */ border: unset; /* initial gibi davranır */ } <style> .parent { color: blue; border: 2px solid red; } .child { all: unset; /* color: blue olur (inherit) border: none olur (initial) */ } </style> revert /* User agent stylesheet'e geri döner */ h1 { font-size: 12px; } h1.special { font-size: revert; /* Browser default h1 size'a döner (32px gibi) */ } revert-layer @layer base { p { color: blue; } } @layer theme { p { color: red; font-size: revert-layer; /* base layer'a döner */ } } 5. ALL ÖZELLİĞİ /* TÜM özellikleri kontrol et */ .reset { all: initial; /* Tüm özellikleri initial yap */ } .inherit-all { all: inherit; /* Tüm özellikleri miras al */ } .unset-all { all: unset; /* Tüm özellikleri unset yap */ } .revert-all { all: revert; /* Tüm özellikleri user agent'a döndür */ } Pratik Örnek: <style> .card { color: red; font-size: 18px; border: 1px solid black; padding: 20px; } .card-content { all: unset; /* color, font-size miras alınır border, padding sıfırlanır */ } </style> <div class="card"> <div class="card-content"> Temiz başlangıç </div> </div> 6. COMPUTED VALUE & INHERITANCE Relative Değerler ve Kalıtım .parent { font-size: 20px; } .child { font-size: 1.5em; /* 30px olur (20px × 1.5) */ } .grandchild { font-size: 1.5em; /* 45px olur (30px × 1.5) - COMPOUNDİNG! */ } Problem: Em değerleri katlanarak büyür! Çözüm: Rem kullan: .parent { font-size: 1.25rem; /* 20px (root 16px ise) */ } .child { font-size: 1.5rem; /* 24px - parent'tan bağımsız */ } Percentage ve Kalıtım .parent { font-size: 20px; line-height: 150%; /* 30px computed value */ } .child { /* line-height: 30px miras alır (computed value) */ /* percentage değil, pixel değeri miras alınır */ } Unitless değerler daha iyi: .parent { font-size: 20px; line-height: 1.5; /* Unitless! */ } .child { font-size: 16px; /* line-height: 1.5 miras alır (ratio) computed: 24px (16px × 1.5) */ } 7. INHERITANCE VE SPECİFİCİTY /* Specificity: 1 */ p { color: red; } /* Specificity: 0 (inherited) */ div { color: blue; } <div> <p>Kırmızı olur!</p> </div> Kural: Doğrudan targeting her zaman inheritance'ı yener, specificity ne olursa olsun! 8. CUSTOM PROPERTIES VE INHERITANCE CSS Variables her zaman inherit edilir: :root { --main-color: blue; --spacing: 20px; } .parent { --main-color: red; /* Override */ } .child { color: var(--main-color); /* red kullanır */ padding: var(--spacing); /* 20px kullanır */ } Cascade ve Inheritance ile Güçlü Patern: :root { --theme-color: blue; } .dark-mode { --theme-color: white; } button { background: var(--theme-color); /* Parent'a göre otomatik değişir */ } .dark-mode { --theme-color: white; } button etiketinin background kuralı hiç değişmez. Değişen tek şey, var(--theme-color) fonksiyonunun bulduğu değerdir. var() fonksiyonu, button elemanının kendisinden başlayarak "ata" zincirinde (parent, grandparent...) yukarı doğru --theme-color değişkenini arar: Normal Buton: Tarayıcı butona bakar: --theme-color tanımlı mı? Hayır. Butonun ebeveyni <body>'ye bakar: Tanımlı mı? Hayır. En tepeye, :root'a bakar: Tanımlı mı? Evet! Değer: blue. Sonuç: background: blue; .dark-mode İçindeki Buton: Tarayıcı butona bakar: Tanımlı mı? Hayır. Butonun ebeveynine bakar (diyelim ki <div class="dark-mode">😞 Tanımlı mı? Evet! Değer: white. (Aramayı durdurur, :root'a gitmesine gerek kalmaz.) Sonuç: background: white; Container Queries: .container { color: blue; } @container (min-width: 400px) { .item { /* color: blue inherit edilir */ font-size: 18px; } } Scope: @scope (.card) { p { /* .card'ın color'unu inherit eder */ } } ÖZET Inheritance mantığı: Tipografi ve metin özellikleri miras alınır Layout ve box model özellikleri miras alınmaz inherit, initial, unset, revert ile kontrol edilir Direct targeting her zaman inheritance'ı yener Computed values miras alınır (percentage'ler değil) CSS Variables her zaman inherit edilir all property ile toplu kontrol Inheritance, CSS'in en güçlü özelliklerinden biri - doğru kullanıldığında kod tekrarını önler ve maintainable stil sistemleri oluşturmayı sağlar!
-
1. TEMEL SELECTORS (Basic Selectors) Universal Selector * { margin: 0; padding: 0; } /* Sayfadaki TÜM elementleri seçer */ Type Selector (Element Selector) div { background: blue; } /* Tüm <div> elementlerini seçer */ Class Selector .button { padding: 10px; } /* class="button" olan tüm elementleri seçer */ .header.active { /* Hem header hem active class'ına sahip elementler */ } ID Selector #main-header { font-size: 24px; } /* id="main-header" olan elementi seçer */ /* ID'ler sayfada benzersiz olmalı */ Attribute Selector /* Temel attribute varlığı */ [disabled] { opacity: 0.5; } /* Tam eşleşme */ [type="text"] { border: 1px solid gray; } /* Başlangıç eşleşmesi */ [href^="https"] { color: green; } /* Bitiş eşleşmesi */ [href$=".pdf"] { background: url(pdf-icon.png); } /* İçerir */ [class*="btn"] { /* class'ında "btn" geçen tüm elementler */ } /* Kelime eşleşmesi */ [class~="active"] { /* class listesinde tam "active" kelimesi olan */ } /* Tire ile başlayan */ [lang|="en"] { /* lang="en" veya lang="en-US" gibi */ } /* Case-insensitive */ [type="text" i] { /* büyük-küçük harf duyarsız */ } 2. COMBINATORS (Birleştiriciler) Descendant Combinator (Boşluk) div p { color: red; } /* div içindeki TÜM <p> elementleri (herhangi bir seviyede) */ <div> <p>Seçilir</p> <section> <p>Bu da seçilir</p> </section> </div> Child Combinator (>) div > p { color: blue; } /* div'in DOĞRUDAN çocuğu olan <p>'ler */ <div> <p>Seçilir</p> <section> <p>Seçilmez (torun)</p> </section> </div> Adjacent Sibling Combinator (+) h1 + p { font-weight: bold; } /* h1'den HEMEN SONRA gelen <p> */ <h1>Başlık</h1> <p>Seçilir</p> <p>Seçilmez</p> General Sibling Combinator (~) h1 ~ p { margin-top: 20px; } /* h1'den SONRA gelen TÜM <p> kardeşleri */ <h1>Başlık</h1> <p>Seçilir</p> <div>Ara element</div> <p>Bu da seçilir</p> 3. PSEUDO-CLASSES (:) Dinamik Durumlar a:hover { color: red; } a:active { color: purple; } a:visited { color: gray; } input:focus { border-color: blue; } button:disabled { opacity: 0.5; } Yapısal Pseudo-Classes /* İlk çocuk */ li:first-child { font-weight: bold; } /* Son çocuk */ li:last-child { border-bottom: none; } /* Belirli sıradaki çocuk */ li:nth-child(3) { color: red; } /* Çift sıradakiler */ li:nth-child(even) { background: #f0f0f0; } /* Tek sıradakiler */ li:nth-child(odd) { background: white; } /* Formül ile */ li:nth-child(3n+1) { /* 1, 4, 7, 10... */ } /* Sondan sayma */ li:nth-last-child(2) { /* Sondan 2. element */ } /* Belirli tipten ilk */ p:first-of-type { margin-top: 0; } /* Belirli tipten son */ p:last-of-type { margin-bottom: 0; } /* Belirli tipten n'inci */ p:nth-of-type(2) { font-size: 18px; } /* Tek çocuk */ div:only-child { text-align: center; } /* Belirli tipten tek */ p:only-of-type { font-style: italic; } /* Boş elementler */ div:empty { display: none; } Mantıksal Pseudo-Classes /* DEĞİL */ p:not(.special) { color: gray; } /* HERHANGİ BİRİ */ :is(h1, h2, h3) { font-family: Arial; } /* Specificity'si 0 olan :is() */ :where(h1, h2, h3) { margin: 0; } /* VARSA */ div:has(> img) { border: 1px solid black; } div:has(+ p) { /* Hemen sonrasında p olan div'ler */ } Form Pseudo-Classes input:required { border-color: red; } input:optional { border-color: gray; } input:valid { border-color: green; } input:invalid { border-color: red; } input:in-range { /* min-max aralığında */ } input:out-of-range { /* min-max dışında */ } input:checked { /* checkbox/radio seçili */ } input:indeterminate { /* belirsiz durum */ } input:read-only { background: #f5f5f5; } input:read-write { background: white; } Diğer Önemli Pseudo-Classes /* Root element (genelde <html>) */ :root { --main-color: blue; } /* Hedef element (URL #hash) */ :target { background: yellow; } /* Dil */ :lang(tr) { quotes: "«" "»"; } 4. PSEUDO-ELEMENTS (::) /* İçeriğin başına */ p::before { content: "→ "; color: blue; } /* İçeriğin sonuna */ p::after { content: " ←"; color: red; } /* İlk satır */ p::first-line { font-weight: bold; } /* İlk harf */ p::first-letter { font-size: 2em; float: left; } /* Seçili metin */ ::selection { background: yellow; color: black; } /* Placeholder */ input::placeholder { color: #999; } /* Marker (liste işaretleri) */ li::marker { color: red; } 6. MODERN VE GELİŞMİŞ SELECTORS :has() - Parent Selector /* İçinde img olan article'lar */ article:has(img) { display: grid; } /* Hemen sonrasında .warning olan div'ler */ div:has(+ .warning) { border: 2px solid red; } /* İçinde checked input olan label'lar */ label:has(input:checked) { font-weight: bold; } :is() ve :where() /* Eski yöntem */ h1 a, h2 a, h3 a { color: blue; } /* Modern yöntem */ :is(h1, h2, h3) a { color: blue; } /* Specificity'yi sıfırlamak için */ :where(h1, h2, h3) a { color: blue; } :not() Gelişmiş Kullanım /* Birden fazla koşul */ button:not(.primary):not(.secondary) { background: gray; } /* Karmaşık selector */ div:not(.container > .item) { padding: 20px; }
-
HTTP/0.9 (1991) - "One-line Protocol" Temel Özellikler Tek Metod: GET - Sadece GET isteği yapılabiliyordu Tek Döküman Tipi: HTML - Yalnızca HTML dosyaları alınabiliyordu Başlıksız İletişim - HTTP header kavramı yoktu Tek Satır İstek - GET /sayfa.html formatında Durum Kodu Yok - Başarı/hata bilgisi yoktu Versiyon Belirtme Yok - HTTP/0.9 yazılmıyordu bile Bağlantı Modeli Her istek için yeni TCP bağlantısı açılıp kapatılıyordu İstek → Yanıt → Bağlantı kapat HTTP/1.0 (1996) - RFC 1945 Yeni Özellikler 1. HTTP Metodları POST: Form verileri ve içerik gönderme HEAD: Sadece başlık bilgisi alma (içerik olmadan): HEAD isteği, sunucudan yalnızca yanıt başlıklarını (headers) alır; sayfanın veya kaynağın asıl içeriğini (body) almaz. Bir dosyanın tamamını (örneğin 10 GB'lık bir video) indirmeden sadece onun hakkında bilgi almak istediğinizde kullanılır. Bu, muazzam bir bant genişliği tasarrufu sağlar. GET metodu devam etti 2. HTTP Headers (Başlıklar) Request Headers: İstemci bilgisi gönderme User-Agent: Tarayıcı bilgisi Accept: Kabul edilen içerik tipleri Authorization: Kimlik doğrulama Response Headers: Sunucu bilgisi alma Content-Type: İçerik tipi (text/html, image/jpeg) Content-Length: İçerik boyutu Date: Yanıt tarihi Server: Sunucu yazılımı 3. Durum Kodları (Status Codes) 1xx: Bilgilendirme 2xx: Başarı (200 OK) 3xx: Yönlendirme (301 Moved, 302 Found) 4xx: İstemci Hataları (404 Not Found, 403 Forbidden) 5xx: Sunucu Hataları (500 Internal Server Error) 4. Versiyon Belirtme İstekte HTTP/1.0 belirtilmeye başlandı Geriye uyumluluk için önemliydi 5. MIME Türü Desteği Çoklu medya tipi desteği Resim, video, ses, PDF gibi dosyalar gönderilebilir oldu Content-Type ile dosya tipi bildirildi 6. Karakter Kodlama Content-Type: text/html; charset=utf-8 şeklinde kodlama belirtme Eksikleri Her istek hala yeni bağlantı gerektiriyordu. Tüm network adımlarının tekrardan yapılması. Performans sorunu vardı (connection overhead) HTTP/1.1 (1997/1999) - RFC 2068/2616 Devrim Niteliğinde Özellikler 1. Persistent Connections (Kalıcı Bağlantılar) Keep-Alive: Tek bağlantı üzerinden çoklu istek, Varsayılan olarak aktif (Connection: keep-alive) TCP bağlantı kurma maliyetini azalttı Connection: close ile kapatılabilir 2. HTTP Pipelining Birden fazla isteği beklemeden arka arkaya gönderme Yanıtlar sırayla dönmek zorunda (FIFO) Pratikte tarayıcılar çok kullanmadı (sorunlar nedeniyle) 3. Host Header (Zorunlu) Sanal sunucu desteği Tek IP'de çoklu domain barındırma GET /index.html HTTP/1.1 Host: ornek.com 4. Yeni HTTP Metodları PUT: Kaynak oluşturma/güncelleme DELETE: Kaynak silme OPTIONS: Sunucu yeteneklerini öğrenme TRACE: İstek yolunu izleme (debug) CONNECT: Proxy için tünel oluşturma 5. Chunked Transfer Encoding İçerik boyutu bilinmeden parça parça gönderim Streaming için ideal Transfer-Encoding: chunked 5\r\n Merhaba\r\n 6\r\n Dünya!\r\n 0\r\n \r\n 6. Gelişmiş Cache Mekanizması ETag: İçerik versiyonlama If-Modified-Since: Koşullu istekler If-None-Match: ETag ile doğrulama Cache-Control: Detaylı önbellek yönetimi max-age, no-cache, no-store, public, private 7. Range Requests (Partial Content) Dosyanın bir bölümünü indirme Download resume özelliği, yarım kalan bir dosya indirme işlemine kaldığı yerden devam edebilme özelliğidir. HTTP/1.1 ile gelen Range Requests sayesinde mümkün olur. Range: bytes=0-1023 206 Partial Content yanıtı 8. Content Negotiation Accept-Language: Dil tercihi Accept-Encoding: Sıkıştırma tercihi (gzip, deflate) Accept-Charset: Karakter seti tercihi Sunucu en uygun içeriği döner 9. Transfer Encoding gzip, compress, deflate sıkıştırma Bandwidth tasarrufu 10. Digest Authentication Basic Auth'tan daha güvenli Şifre hash'lenerek gönderilir Sorunları Head-of-Line Blocking: Bir istek yavaşsa diğerleri bekler Header Overhead: Her istekte tekrar eden başlıklar TCP Limitasyonu: TCP'nin kendi blocking sorunları HTTP/2 (2015) - RFC 7540 Paradigma Değişimi 1. Binary Protocol (İkili Protokol) Metin yerine ikili format Parse etme daha hızlı ve hatasız Frames ve streams yapısı Frame Types: - HEADERS: Başlık bilgileri - DATA: Veri içeriği - SETTINGS: Bağlantı ayarları - WINDOW_UPDATE: Akış kontrolü - PRIORITY: Önceliklendirme 2. Multiplexing (Çoğullama) Tek TCP bağlantısı üzerinde paralel istekler Her istek bir "stream" ID'si alır Yanıtlar sırasız gelebilir (interleaved) Head-of-line blocking çözüldü (HTTP seviyesinde) 3. Stream Prioritization (Önceliklendirme) Her stream'e ağırlık (weight) atanabilir Dependency tree oluşturma Kritik kaynaklar önce yüklenebilir Stream 1 (HTML): Weight 256, Parent: 0 Stream 3 (CSS): Weight 220, Parent: 1 Stream 5 (JS): Weight 220, Parent: 1 Stream 7 (Image): Weight 32, Parent: 1 4. Server Push Sunucu istek beklemeden kaynak gönderebilir İstemci henüz talep etmediği kaynakları push edebilir Örnek: HTML gönderilirken CSS ve JS de push edilir PUSH_PROMISE frame ile bildirim 5. Header Compression (HPACK) Başlıkları sıkıştırma algoritması Statik tablo: Yaygın başlıklar için Dinamik tablo: Önceki başlıkları referans alma %85-95 arası boyut azaltma Sıkıştırılmamış: 800 bytes HPACK ile: 100 bytes 6. Flow Control (Akış Kontrolü) Stream ve bağlantı seviyesinde kontrol Receiver buffer overflow önleme WINDOW_UPDATE frame'leri ile yönetim 7. Stream Reset İstemci/sunucu stream'i iptal edebilir RST_STREAM frame Tüm bağlantıyı kapatmadan iptal 8. HTTPS Zorunluluğu (Pratikte) Tarayıcılar sadece TLS üzerinden destekler Güvenlik artışı 9. ALPN (Application-Layer Protocol Negotiation) TLS handshake sırasında protokol seçimi HTTP/1.1 veya HTTP/2 anlaşması Sorunları TCP Head-of-Line Blocking: TCP seviyesinde hala var Paket kaybında tüm stream'ler etkilenir Connection Migration: IP değişirse bağlantı kopar HTTP/3 (2022) - RFC 9114 QUIC Temelli Yenilik 1. QUIC Transport Protokolü UDP tabanlı: TCP yerine UDP kullanır TCP'nin head-of-line blocking'i ortadan kalkar Kullanıcı alanında (userspace) çalışır Kernel güncellemesi gerektirmez 2. 0-RTT Connection Establishment İlk bağlantı: 1-RTT Sonraki bağlantılar: 0-RTT Önceki session bilgisi ile hemen veri gönderilebilir İlk Bağlantı: ClientHello → ServerHello → Application Data (1-RTT) Sonraki Bağlantılar: ClientHello + Early Data (0-RTT) 3. Connection Migration IP adresi değişse bile bağlantı devam eder WiFi → 4G geçişinde bağlantı kopmuyor Connection ID ile tracking Mobil cihazlar için harika 4. Independent Streams Her stream bağımsız Bir stream'de paket kaybı diğerlerini etkilemez TCP'deki head-of-line blocking tamamen çözüldü 5. Built-in Encryption (TLS 1.3) Varsayılan ve zorunlu şifreleme TLS 1.3 QUIC'e entegre Daha hızlı handshake Downgrade attack önleme 6. Improved Congestion Control Daha gelişmiş paket kaybı algılama Daha iyi bandwidth tahmini BBR (Bottleneck Bandwidth and Round-trip propagation time) 7. Flexible Frame Structure Genişletilebilir frame yapısı Gelecekte yeni özellikler eklenebilir 8. Improved Loss Detection Monoton artan paket numaraları Daha hassas RTT ölçümü Spurious retransmission önleme 9. Connection Close Graceful shutdown Hata kodları ile detaylı kapanış nedeni 10. Version Negotiation QUIC versiyonu pazarlığı Geriye uyumluluk Performans Karşılaştırması Bağlantı Kurma Süresi: HTTP/1.1: 3 RTT (TCP + TLS) HTTP/2: 3 RTT (TCP + TLS + ALPN) HTTP/3: 0-1 RTT (QUIC) Paket Kaybında (%1): HTTP/1.1: ~30% yavaşlama HTTP/2: ~15% yavaşlama HTTP/3: ~2% yavaşlama Mobil Ağlarda: HTTP/2: Sık bağlantı kopması HTTP/3: Sorunsuz geçiş
-
Critical Rendering Path (Kritik İşleme Yolu), bir tarayıcının yazdığınız HTML, CSS ve JavaScript kodunu alıp kullanıcının ekranında görebileceği piksellere dönüştürme sürecindeki adımların tamamıdır. Bu yolun hızlı olması, web sitenizin performansını ve kullanıcı deneyimini (özellikle LCP - Largest Contentful Paint gibi Core Web Vitals metriklerini) doğrudan etkiler. 1. HTML'i Oku → DOM Ağacı Oluştur Tarayıcı HTML'i satır satır okur ve bir ağaç yapısı oluşturur. <div> <h1>Başlık</h1> <p>Paragraf</p> </div> Bu bir ağaç haline gelir: div → (h1, p) 2. CSS'i Oku → CSSOM Ağacı Oluştur CSS kuralları da bir ağaç yapısına dönüştürülür. div { padding: 20px; } h1 { color: blue; } Önemli: CSS hazır olmadan sayfa gösterilemez! CSS Render-Blockingtir. Sayfada style dosyası ile karşılaştığında renderi ve parse yi durdurur. CSS render-blocking = Tarayıcı, CSS dosyası tamamen yüklenip işlenene kadar sayfayı ekrana çizmez (render etmez). Yani kullanıcı boş beyaz ekran görür, CSS hazır olana kadar bekler. Neden Böyle? Tarayıcı şunu önlemek ister: FOUC (Flash of Unstyled Content) = Stilsiz içeriğin görünmesi. Bunun yerine tarayıcı der ki: "CSS gelene kadar hiçbir şey gösterme!" Sayfa aşama aşma yüklenip parse edildiğinden, ekrana basılan elementlerden sonra css stili varsa tekrar sayfa içeriği render edilir. Bu nedenle css dosyalarını yada stillerini html elementlerinde önce tanımlamamız gerekir. 3. DOM + CSSOM → Render Ağacı İki ağaç birleştirilir. Sadece ekranda görünecek elementler dahil edilir. display: none olanlar çıkarılır head, script gibi görünmezler çıkarılır 4. Layout (Düzen Hesaplama)(Reflow) Her elementin ekranda nerede duracağı ve ne kadar yer kaplayacağı hesaplanır. Boyutlar (width, height) Konumlar (top, left) Margin, padding değerleri // LAYOUT + PAINT + COMPOSITE element.style.width = '100px'; element.style.height = '200px'; element.style.margin = '10px'; element.style.padding = '20px'; element.style.display = 'flex'; element.style.position = 'absolute'; // Okuma işlemleri de layout tetikler! const height = element.offsetHeight; // ⚠️ Layout! const width = element.getBoundingClientRect().width; // ⚠️ Layout! ``` **Süreç:** ``` LAYOUT ⚙️⚙️⚙️ (3/10 maliyet) ↓ PAINT ⚙️⚙️ (2/10 maliyet) ↓ COMPOSITE ⚙️ (1/10 maliyet) 5. Paint (Boyama) Tarayıcı pikselleri boyamaya başlar: Renkler Metinler Resimler Gölgeler // Layout atlar, sadece PAINT + COMPOSITE element.style.color = 'red'; element.style.background = 'blue'; element.style.boxShadow = '0 0 10px black'; element.style.borderRadius = '5px'; ``` **Süreç:** ``` LAYOUT ❌ (atlandı) ↓ PAINT ⚙️⚙️ (2/10 maliyet) ↓ COMPOSITE ⚙️ (1/10 maliyet) 6. Composite (Birleştirme) Katmanlar birleştirilerek son görüntü oluşturulur ve ekrana verilir. Tüm katmanları doğru sırada birleştirir ve ekrana gönderir: Layer 1 (arka plan) + Layer 2 (kenarlıklar) + Layer 3 (metin) + Layer 4 (gölgeler) ↓ GPU'da birleştir EKRANA GÖNDER! 📺 // Layout ve Paint atlar, sadece COMPOSITE element.style.transform = 'translateX(100px)'; element.style.opacity = '0.5'; element.style.filter = 'blur(5px)'; // GPU'da ``` **Süreç:** ``` LAYOUT ❌ (atlandı) ↓ PAINT ❌ (atlandı) ↓ COMPOSITE ⚙️ (1/10 maliyet) - GPU'da! JavaScript'in Etkisi JavaScript bu süreci durdurur: <!-- Sayfa render'ı durur, JS inene kadar bekler --> <script src="app.js"></script> <!-- Sayfa render'ı durdurmaz (daha iyi) --> <script src="app.js" defer></script> Hızlandırma İpuçları CSS: Dosya boyutunu küçük tut Gereksiz kuralları temizle JavaScript: defer veya async kullan Script'leri body sonuna koy HTML: Gereksiz element kullanma Basit yapılar tercih et Sonuç: Bu 6 adım ne kadar hızlı tamamlanırsa, kullanıcı sayfayı o kadar çabuk görür! Sayfa yüklenirken render TEK SEFERDE olmaz, defalarca tekrarlanır. Her render'dan sonra da Layout → Paint → Composite döngüsü çalışır. Render Nedir? (Tam Süreç) Render = Ekrana piksel çizme işleminin TAMAMIDIR Render süreci: 1. Render Tree oluştur (DOM + CSSOM birleştir) 2. Layout (Boyut ve konum hesapla) 3. Paint (Pikselleri boya) 4. Composite (Katmanları birleştir) ↓ Ekranda görünür piksel! 🖼️
-
Networking Aşaması Tarayıcının bir URL'den HTML içeriğini alması sürecidir. 1. URL Parsing (URL Ayrıştırma) Kullanıcı bir URL girdiğinde veya link tıkladığında, tarayıcı önce URL'i parçalarına ayırır: https://herseyibul.com:443/path/page.html?id=123#section └─┬─┘ └────┬────────┘└┬┘└─────┬───────┘ └──┬──┘└──┬──┘ Protocol Host Port Path Query Fragment 2. DNS Lookup (DNS Sorgusu) DNS Resolution Süreci: Domain adı(host) IP adresine çevrilir. Tarayıcı sırasıyla şu kaynaklara bakar: Browser DNS Cache: Tarayıcı kendi önbelleğini kontrol eder OS DNS Cache: İşletim sistemi önbelleği kontrol edilir Router Cache: Local ağdaki router önbelleği ISP DNS Server: ISP'nin DNS sunucusu sorgulanır Root DNS → TLD DNS → Authoritative DNS: Hiyerarşik sorgulama DNS sorgusu tipik olarak 20-120ms sürer. Modern tarayıcılar DNS prefetching kullanarak bu süreci hızlandırır. DNS prefetching (DNS önceden getirme), tarayıcınıza gelecekte ihtiyaç duyulacağını bildiğiniz harici alan adlarının (domain) IP adreslerini arka planda, kullanıcı henüz o alan adıyla ilgili bir kaynağı (resim, script, font) talep etmeden önce çözmesi (lookup) için verdiğiniz bir "ipucudur". ... <head> <meta charset="UTF-8"> <title>Web Sitem</title> <link rel="dns-prefetch" href="//fonts.googleapis.com"> <link rel="dns-prefetch" href="//www.google-analytics.com"> ... 3. TCP Connection (TCP Bağlantısı) TCP Bağlantısı: Verinin güvenilir bir şekilde (kayıpsız) taşınacağı boru hattını (pipe) inşa eder. TCP 3-Way Handshake: Client → Server: SYN (Synchronize) Server → Client: SYN-ACK (Synchronize-Acknowledge) Client → Server: ACK (Acknowledge) Bu işlem bir RTT (Round Trip Time) sürer, tipik olarak 30-100ms. Bağlantı kurulduktan sonra veri transferi başlayabilir. RTT, "Round Trip Time" (Gidiş-Dönüş Süresi) anlamına gelir. En basit tanımıyla RTT, sizin bilgisayarınızdan (istemci) bir sunucuya bir veri paketinin gitmesi ve o pakete karşılık bir cevabın (onayın) sunucudan size geri dönmesi için geçen toplam süredir. 4. TLS/SSL Handshake (HTTPS için) Bu boru hattının içinden geçecek veriyi şifreler ve kimlik doğrulaması yapar. HTTPS bağlantılarında ek olarak TLS handshake yapılır: Client Hello → (cipher suites, TLS version) Server Hello → (selected cipher, certificate) Key Exchange → (session keys oluşturulur) Finished → (encrypted communication başlar) TLS 1.3 ile bu süreç 1 RTT'ye düşürüldü (önceden 2 RTT idi). Certificate validation, OCSP (Online Certificate Status Protocol) kontrolü de bu aşamada yapılır. TLS 1.3, bir siteyi tekrar ziyaret ettiğinizde bu süreci 0-RTT'ye (TLS için) bile düşürebilir. OCSP (Online Certificate Status Protocol), bir SSL/TLS sertifikasının hala geçerli olup olmadığını veya iptal edilip edilmediğini (revoked) kontrol etmek için kullanılan bir internet protokolüdür. OCSP: Tarayıcının, sertifikanın iptal durumunu CA'e sormasıdır (Yavaş ve gizlilik sorunu var). OCSP Stapling: Sunucunun, sertifika durumunu düzenli olarak CA'den alıp, gelen ziyaretçilere (tarayıcılara) sertifikayla beraber "zımbalayarak" sunmasıdır (Hızlı ve gizlidir). Web performansını ve güvenliğini önemsiyorsanız, sunucunuzda OCSP Stapling'in mutlaka etkinleştirilmiş olması gerekir. 5. HTTP Request(İstek) Basitçe söylemek gerekirse, bir tarayıcının (istemci), bir web sunucusuna bir kaynak (dosya, veri) almak veya bir eylem gerçekleştirmek için gönderdiği resmi mesajdır. Bir web sitesinde tıkladığınız her link, tarayıcınızın adres çubuğuna yazdığınız her adres veya gönderdiğiniz her form, arka planda bir HTTP İsteği oluşturur. GET /index.html HTTP/2 Host: herseyibul.com User-Agent: Mozilla/5.0... Accept: text/html,application/xhtml+xml... Accept-Language: tr-TR,tr;q=0.9 Accept-Encoding: gzip, deflate, br Cache-Control: no-cache Connection: keep-alive Cookie: session_id=abc123... 6. Server Processing(Sunucu İşlemesi) Bu, bir web sitesinin "beynidir" ve isteğin (request) gelmesi ile yanıtın (response) gönderilmesi arasında olan her şeyi kapsar. 7. HTTP Response HTTP Response, sunucunun, aldığı HTTP İsteği'ne karşılık olarak istemciye (tarayıcıya) gönderdiği "cevap" mesajıdır. Bu cevap, istenen kaynağın kendisi (HTML sayfası, resim) veya işlemin durumu (hata, yönlendirme) olabilir.
-
"Cascade" (Çağlayan veya Basamaklanma), CSS'in "C" harfini oluşturan temel ve en önemli kavramdır. Bir HTML elemanına birden fazla stil kuralı uygulanmaya çalıştığında, hangi kuralın "kazanacağını" ve son sözü söyleyeceğini belirleyen algoritmadır. Resim Kaynağı: https://css-tricks.com/css-cascade-layers/ Çağlayanın Temel Amacı: Hangi Stil Kazanacak? Bir p etiketimiz olduğunu düşünün. Bu etikete stil veren kurallar şunlar olabilir: Tarayıcının kendi varsayılan stili (örn: margin-bottom: 16px) style.css dosyanızdaki bir kural (örn: p { color: blue; }) Aynı dosyadaki başka bir kural (örn: .content p { color: red; }) HTML içindeki bir style özelliği (örn: <p style="color: green;">) Hepsi aynı color özelliğini değiştirmeye çalışıyor. Tarayıcı yeşili mi, kırmızıyı mı yoksa maviyi mi seçecek? İşte bu kararı CSS Cascade algoritması verir. 1. Adım: Kaynak (Origin) ve Önem (!important) Tarayıcı ilk olarak stilin nereden geldiğine ve ne kadar önemli olarak işaretlendiğine bakar. Kaynaklar (Origins): Stillerin 3 temel kaynağı vardır, öncelik sırasına göre (düşükten yükseğe): A - Tarayıcı Stilleri (User-Agent): Tarayıcınızın kendi varsayılan stilleridir. (Örn: <h1> etiketinin büyük olması, linklerin mavi ve altı çizgili olması). En düşük önceliğe sahiptir. /* Chrome'un varsayılan stilleri (basitleştirilmiş) */ /* Blok elementler */ div, p, h1, h2, section, article { display: block; } /* Paragraflar */ p { display: block; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; } /* Başlıklar */ h1 { display: block; font-size: 2em; margin-block-start: 0.67em; margin-block-end: 0.67em; font-weight: bold; } /* Listeler */ ul, ol { display: block; list-style-type: disc; margin-block-start: 1em; margin-block-end: 1em; padding-inline-start: 40px; } /* Linkler */ a { color: -webkit-link; cursor: pointer; text-decoration: underline; } /* Formlar */ button, input, select, textarea { font-family: inherit; font-size: 100%; } ``` ### User-Agent Stilleri Nerede? Tarayıcı kaynak kodlarında: ``` Chromium: https://chromium.googlesource.com/chromium/blink/+/master/Source/core/css/html.css Firefox: https://searchfox.org/mozilla-central/source/layout/style/res/html.css Safari (WebKit): https://trac.webkit.org/browser/trunk/Source/WebCore/css/html.css B - Kullanıcı Stilleri (User): Kullanıcının (genellikle erişilebilirlik nedenleriyle) kendi tarayıcısına eklediği özel stiller. (Örn: "Tüm web sitelerindeki yazı tipini 18px yap"). "Kullanıcı Stili Eklentisi", sizin (kullanıcının) ziyaret ettiğiniz web sitelerinin CSS kodlarını geçersiz kılmak (override etmek) ve kendi özel CSS kurallarınızı uygulamanızı sağlayan bir tarayıcı aracıdır. Bu eklentilerin en bilineni ve günümüzde en çok tavsiye edileni Stylus'tır. /* Kullanıcının tarayıcıya eklediği stil */ body { background: black !important; color: yellow !important; font-size: 24px !important; } a { color: cyan !important; text-decoration: underline !important; } Bu stil örneğinde tüm stil kuralları geçerli olması için !important kullanıldığına dikkat edin. C - Yazar Stilleri (Author): Sizin (web geliştiricisinin) yazdığı CSS kodlarıdır. style.css dosyanız, <style> etiketleriniz vb. Normalde en yüksek önceliğe sahiptir. Normal Akış: Yazar Stilleri > Kullanıcı Stilleri > Tarayıcı Stilleri İstisna: !important !important bayrağı, bu sıralamayı alt üst eder. Bir kurala !important eklendiğinde, o kural "süper güç" kazanır ve sıralama tersine döner: Tarayıcı Stilleri > Kullanıcı Stilleri > Yazar Stilleri Tarayıcı stilleri genellikle !important kullanmazlar. <!DOCTYPE html> <html> <head> <!-- 1. External Stylesheet --> <link rel="stylesheet" href="style.css"> <!-- 2. Internal Stylesheet --> <style> p { color: blue; } </style> <!-- 3. Imported Stylesheet --> <style> @import url('theme.css'); </style> </head> <body> <!-- 4. Inline Styles --> <p style="color: red;">Merhaba</p> <!-- 5. JavaScript ile eklenen --> <script> document.querySelector('p').style.color = 'green'; </script> </body> </html> 2. CSS Inline Styles Inline styles, HTML elementlerine doğrudan style attribute'u ile eklenen CSS stilleridir. <p style="color: red; font-size: 18px; margin: 10px;"> Inline stil örneği </p> Inline Styles Özellikleri 1. Specificity (Özgüllük) Değeri Inline styles, CSS specificity hesaplamasında en yüksek değere sahiptir Specificity değeri: 1,0,0,0 (1000 puan) Selectorlerle yazılan hemen hemen tüm stillerden önceliklidir <style> /* Specificity: 0,1,0,1 = 101 puan */ #header p { color: blue; } /* Specificity: 0,0,1,1 = 11 puan */ .text p { color: green; } </style> <!-- Inline style kazanır (1000 puan) --> <div id="header" class="text"> <p style="color: red;">Bu metin kırmızı olacak</p> </div> 2. Cascade Konumu Inline styles, CSS cascade sırasında çok üst seviyede yer alır: Transition (geçiş sırasında) !important user agent styles !important user styles !important author styles Animation (animasyon sırasında) Normal author styles Normal user styles Normal user agent styles Inline styles "normal author styles" kategorisine girer, ancak çok yüksek specificity'si sayesinde diğer normal stillerin hepsini ezer. !important vs Inline Styles Evet, !important inline style'ı geçer! <style> p { color: blue !important; } </style> <!-- Paragraf MAVI olacak, kırmızı değil --> <p style="color: red;">Bu metin mavi olacak</p> Öncelik Sırası <style> /* 1. En güçlü: !important + yüksek specificity */ #text { color: purple !important; } /* 2. Orta güçlü: !important + düşük specificity */ p { color: blue !important; } /* 3. Zayıf: inline style (1000 puan ama !important yok) */ /* style="color: red;" */ /* 4. En zayıf: normal selector */ p { color: green; } </style> <p id="text" style="color: red;"> Bu metin PURPLE olacak </p> Detaylı Cascade Sıralaması: /* Kazanan stiller (yukarıdan aşağıya öncelik) */ /* 1. !important inline style - EN GÜÇLÜ */ <div style="color: red !important;"> /* 2. !important ile yazılmış stiller (specificity'e göre) */ #id { color: blue !important; } .class { color: green !important; } div { color: yellow !important; } /* 3. Normal inline style */ <div style="color: red;"> /* 4. Normal CSS kuralları (specificity'e göre) */ #id { color: blue; } .class { color: green; } div { color: yellow; } Inline Style'da !important Kullanımı <!-- İki !important varsa, inline olan kazanır --> <style> p { color: blue !important; } </style> <!-- Bu metin KIRMIZI olacak --> <p style="color: red !important;"> Inline !important kazandı </p> 3. CSS Cascade Layers (@layer) CSS Cascade Layers, CSS'in cascade (basamaklandırma) mekanizmasını kontrol etmek için modern bir özelliktir. Stillerin öncelik sırasını organize etmeye yarar. Temel Kullanım: /* Layer tanımlama ve stil ekleme */ @layer base { h1 { color: blue; font-size: 2em; } } @layer components { h1 { color: red; } } @layer utilities { h1 { color: green; } } Layer Öncelik Sırası Önemli Kural: Daha önce tanımlanan layer, daha sonra tanımlanan layer'dan daha düşük önceliğe sahiptir. /* Layer sırasını önceden belirle */ @layer base, components, utilities; /* base < components < utilities önceliğinde */ @layer base { button { background: blue; } } @layer utilities { button { background: green; } /* Bu kazanır */ } @layer components { button { background: red; } } /* Sonuç: button yeşil olacak (utilities en son sırada) */ Layer'sız Stiller Layer'a atanmamış stiller, tüm layer'lardan daha yüksek önceliğe sahiptir: @layer base { p { color: blue; } } @layer components { p { color: red; } } /* Layer dışı stil - EN YÜKSEK ÖNCELİK */ p { color: green; /* Bu kazanır */ } Önemli: !important kullanıldığında layer öncelik sırası tersine döner! @layer A, B, C; /* Normal stiller: A < B < C */ /* !important stiller: C < B < A */ @layer A { div { color: red; } span { color: blue !important; } /* !important: en güçlü */ } @layer B { div { color: green; } span { color: green !important; } } @layer C { div { color: blue; } /* Normal: kazanır */ span { color: red !important; } /* !important: en zayıf */ } 4. CSS Selector Specificity (Özgüllük) Specificity, CSS'de aynı elemente birden fazla stil kuralı uygulandığında hangisinin geçerli olacağını belirleyen ağırlık hesaplama sistemidir. Specificity Değer Sistemi Specificity, 4 basamaklı bir değer sistemiyle hesaplanır: (a, b, c, d) a - Inline styles (1,0,0,0) b - ID selectors (#id) c - Class, attribute, pseudo-class selectors d - Element, pseudo-element selectors /* (0,0,0,1) = 1 puan */ p { color: blue; } /* (0,0,1,0) = 10 puan */ .text { color: red; } /* (0,1,0,0) = 100 puan */ #header { color: green; } /* (1,0,0,0) = 1000 puan */ <p style="color: yellow;"> 5. CSS Scope Proximity (Kapsam Yakınlığı) Scope proximity, CSS'in @scope kuralı ile gelen ve DOM ağacında hangi scope'un elemente daha yakın olduğunu belirleyen bir cascade kriteri olarak 2023-2024'te CSS spesifikasyonuna eklenen modern bir özelliktir. @scope Nedir? @scope kuralı, stillerin belirli bir DOM alt ağacına (subtree) uygulanmasını sağlar: @scope (.card) { /* Bu stiller sadece .card içinde geçerli */ h2 { color: blue; } p { margin: 0; } } Scope Proximity Prensibi Birden fazla scope aynı elemente stil uyguladığında, DOM'da elemente en yakın olan scope kazanır - specificity'den bağımsız olarak! <div class="outer"> <div class="inner"> <p>Bu paragraf</p> </div> </div> /* Outer scope - uzak */ @scope (.outer) { p { color: blue; font-size: 16px; } } /* Inner scope - YAKIN */ @scope (.inner) { p { color: red; /* KAZANIR - daha yakın scope */ font-size: 20px; } } Sonuç: Paragraf kırmızı ve 20px olacak çünkü .inner scope'u DOM'da paragrafa daha yakın. Scope Proximity vs Specificity Önemli: Scope proximity, specificity'den daha önceliklidir! /* Yüksek specificity ama uzak scope */ @scope (.outer) { #content p.highlight { color: blue; /* Specificity: (0,1,1,1) = 111 */ } } /* Düşük specificity ama yakın scope */ @scope (.inner) { p { color: red; /* KAZANIR - yakın scope */ /* Specificity: (0,0,0,1) = 1 */ } } 6. CSS Source Order (Kaynak Sırası) Source Order, CSS cascade sisteminde aynı origin, context, layer, scope proximity, ve specificity'ye sahip iki veya daha fazla stil kuralı olduğunda, hangisinin geçerli olacağını belirleyen son kriterdir. Basitçe: En son yazılan kural kazanır. CSS Cascade Sıralaması (yukarıdan aşağıya): 1. Origin & Importance (!important) 2. Context (Shadow DOM) 3. Element-attached styles (inline) 4. Layers (@layer) 5. Scope proximity (@scope) 6. Specificity (selector ağırlığı) 7. SOURCE ORDER ← En son kriter
