Duyarlı ve erişilebilir bir anahtar bileşeni oluşturmaya dair temel bilgiler.
Bu yayında, anahtar bileşenlerini oluşturmanın bir yolu hakkındaki düşüncelerimi paylaşmak istiyorum. Demoyu deneyin.
Videoyu tercih ediyorsanız bu yayının YouTube sürümünü burada bulabilirsiniz:
Genel Bakış
Anahtar, onay kutusuna benzer şekilde çalışır ancak açık ve kapalı boole durumlarını açıkça gösterir.
Bu demodaki işlevlerin çoğunda <input type="checkbox" role="switch">
kullanılır. Bu da, CSS veya JavaScript'in tamamen işlevsel ve erişilebilir olmasına gerek olmaması avantajına sahiptir. CSS'nin yüklenmesi, sağdan sola yazılan diller, dikeylik, animasyon ve daha fazlası için destek sağlar. JavaScript'i yüklemek, anahtarı sürüklenebilir ve somut hale getirir.
Özel özellikler
Aşağıdaki değişkenler, anahtarın çeşitli bölümlerini ve seçeneklerini temsil eder. Üst düzey sınıf olarak .gui-switch
, bileşen alt öğeleri genelinde kullanılan özel özellikleri ve merkezi özelleştirme için giriş noktalarını içerir.
Parça
Uzunluk (--track-size
), dolgu ve iki renk:
.gui-switch {
--track-size: calc(var(--thumb-size) * 2);
--track-padding: 2px;
--track-inactive: hsl(80 0% 80%);
--track-active: hsl(80 60% 45%);
--track-color-inactive: var(--track-inactive);
--track-color-active: var(--track-active);
@media (prefers-color-scheme: dark) {
--track-inactive: hsl(80 0% 35%);
--track-active: hsl(80 60% 60%);
}
}
Küçük resim
Boyut, arka plan rengi ve etkileşim renkleri vurgulanır:
.gui-switch {
--thumb-size: 2rem;
--thumb: hsl(0 0% 100%);
--thumb-highlight: hsl(0 0% 0% / 25%);
--thumb-color: var(--thumb);
--thumb-color-highlight: var(--thumb-highlight);
@media (prefers-color-scheme: dark) {
--thumb: hsl(0 0% 5%);
--thumb-highlight: hsl(0 0% 100% / 25%);
}
}
Az hareket
Net bir takma ad eklemek ve tekrarı azaltmak için, PostCSS eklentisi ile özel bir mülke azaltılmış hareket tercihi kullanıcı medya sorgusu eklenebilir. Bu işlem, Media Queries 5'teki taslak spesifikasyonu temel alınarak yapılır:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
Brüt kar
Onay kutusu ve etiket ilişkilendirmesi belirsizliğini önlemek için <input type="checkbox" role="switch">
öğemi bir <label>
ile sarmalamayı tercih ettim. Aynı zamanda kullanıcıya, girişi açıp kapatabilmek için etiketle etkileşimde bulunma olanağı da verdim.
<label for="switch" class="gui-switch">
Label text
<input type="checkbox" role="switch" id="switch">
</label>
<input type="checkbox">
, önceden oluşturulmuş bir API ve durum ile birlikte sunulur. Tarayıcı, checked
mülkünü ve oninput
ile onchanged
gibi giriş etkinliklerini yönetir.
Düzenler
Flexbox, grid ve özel özellikler, bu bileşenin stillerinin korunmasında kritik öneme sahiptir. Değerleri merkezileştirir, aksi takdirde belirsiz olan hesaplamalara veya alanlara ad verir ve kolay bileşen özelleştirmeleri için küçük bir özel mülk API'si etkinleştirir.
.gui-switch
Geçiş için üst düzey düzen, flexbox'tur. .gui-switch
sınıfı, çocukların düzenleri hesaplamak için kullandığı özel ve herkese açık özel mülkleri içerir.
.gui-switch {
display: flex;
align-items: center;
gap: 2ch;
justify-content: space-between;
}
Flexbox düzenini genişletmek ve değiştirmek, herhangi bir flexbox düzenini değiştirmeye benzer.
Örneğin, bir anahtarın üzerine veya altına etiket koymak ya da flex-direction
:
<label for="light-switch" class="gui-switch" style="flex-direction: column">
Default
<input type="checkbox" role="switch" id="light-switch">
</label>
Parça
Onay kutusu girişi, normal appearance: checkbox
boyutu kaldırılarak ve kendi boyutu sağlanarak anahtar yolu olarak biçimlendirilir:
.gui-switch > input {
appearance: none;
inline-size: var(--track-size);
block-size: var(--thumb-size);
padding: var(--track-padding);
flex-shrink: 0;
display: grid;
align-items: center;
grid: [track] 1fr / [track] 1fr;
}
Parça, küçük resim için tek tek tek hücreli bir ızgara parça alanı da oluşturur.
Küçük resim
appearance: none
stili, tarayıcı tarafından sağlanan görsel onay işaretini de kaldırır. Bu bileşen, bu görsel göstergenin yerini almak için girişte bir sözde öğe ve :checked
sözde sınıf kullanır.
Başparmak, input[type="checkbox"]
öğesine bağlı bir sözde öğe alt öğesidir ve track
ızgara alanını talep ederek kanalın altında değil üstünde yığınlanır:
.gui-switch > input::before {
content: "";
grid-area: track;
inline-size: var(--thumb-size);
block-size: var(--thumb-size);
}
Stiller
Özel özellikler; renk şemalarına, sağdan sola dillere ve hareket tercihlerine uyum sağlayan çok yönlü bir anahtar bileşeni sağlar.
Dokunmatik etkileşim stilleri
Mobil cihazlarda tarayıcılar, etiketlere ve girişlere dokunma vurguları ve metin seçim özellikleri ekler. Bu sorunlar, bu geçiş için gereken stil ve görsel etkileşim geri bildirimini olumsuz yönde etkiledi. Birkaç satır CSS ile bu efektleri kaldırabilir ve kendi cursor: pointer
stilimi ekleyebilirim:
.gui-switch {
cursor: pointer;
user-select: none;
-webkit-tap-highlight-color: transparent;
}
Bu stillerin kaldırılması, değerli görsel etkileşim geri bildirimi olabileceği için her zaman tavsiye edilmez. Kaldırırsanız özel alternatifler sunduğunuzdan emin olun.
Parça
Bu öğenin stilleri, çoğunlukla şekli ve rengiyle ilgilidir. Bu stillere, kademeli aracılığıyla üst .gui-switch
öğesinden erişir.
.gui-switch > input {
appearance: none;
border: none;
outline-offset: 5px;
box-sizing: content-box;
padding: var(--track-padding);
background: var(--track-color-inactive);
inline-size: var(--track-size);
block-size: var(--thumb-size);
border-radius: var(--track-size);
}
Geçiş yolu için dört özel mülkten çok çeşitli özelleştirme seçenekleri elde edilebilir. appearance: none
, tüm tarayıcılarda onay kutusunun kenarlıklarını kaldırmadığı için border: none
eklenir.
Küçük resim
Küçük resim öğesi zaten sağ tarafta track
ancak daire stillerine ihtiyacı var:
.gui-switch > input::before {
background: var(--thumb-color);
border-radius: 50%;
}
Etkileşim
Fareyle üzerine gelmeyle vurgulanan öğeleri ve başparmak konumu değişikliklerini gösterecek etkileşimlere hazırlanmak için özel mülkleri kullanın. Hareket veya fareyle üzerine gelme stillerini geçirmeden önce kullanıcının tercihi de kontrol edilir.
.gui-switch > input::before {
box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);
@media (--motionOK) { & {
transition:
transform var(--thumb-transition-duration) ease,
box-shadow .25s ease;
}}
}
Başparmak konumu
Özel mülkler, başparmağı parçaya yerleştirmek için tek bir kaynak mekanizması sağlar. Başparmak kaydırma çubuğunu doğru şekilde kaydırarak kaydırma çubuğu içinde tutabilmek için hesaplamalarda kullanacağımız kaydırma çubuğu ve başparmak boyutları (0%
ve 100%
) mevcuttur.
input
öğesi --thumb-position
konum değişkenine sahiptir ve başparmak sözde öğesi bunu translateX
konumu olarak kullanır:
.gui-switch > input {
--thumb-position: 0%;
}
.gui-switch > input::before {
transform: translateX(var(--thumb-position));
}
Artık CSS'deki --thumb-position
ve onay kutusu öğelerinde sağlanan sözde sınıfları değiştirebiliriz. Bu öğede transition: transform
var(--thumb-transition-duration) ease
koşullu olarak daha önce ayarlandığından, aşağıdaki değişiklikler değiştirildiğinde animasyonlu olabilir:
/* positioned at the end of the track: track length - 100% (thumb width) */
.gui-switch > input:checked {
--thumb-position: calc(var(--track-size) - 100%);
}
/* positioned in the center of the track: half the track - half the thumb */
.gui-switch > input:indeterminate {
--thumb-position: calc(
(var(--track-size) / 2) - (var(--thumb-size) / 2)
);
}
Bu bağımsız düzenlemenin işe yaradığını düşünmüştüm. Küçük resim öğesi yalnızca bir stil (translateX
konumu) ile ilgilenir. Bu girdi, tüm karmaşıklığı
ve hesaplamaları yönetebilir.
Sektör
Destek, input
öğesine CSS dönüşümleriyle dönme ekleyen bir değiştirici sınıf -vertical
ile sağlandı.
3D döndürülmüş bir öğe, bileşenin toplam yüksekliğini değiştirmez. Bu da blok düzenini bozabilir. --track-size
ve --track-padding
değişkenlerini kullanarak bunu hesaba katın. Dikey bir düğmenin düzende beklendiği gibi akması için gereken minimum alan miktarını hesaplayın:
.gui-switch.-vertical {
min-block-size: calc(var(--track-size) + calc(var(--track-padding) * 2));
& > input {
transform: rotate(-90deg);
}
}
(RTL) sağdan sola
CSS uzmanı bir arkadaşım olan Elad Schecter ile birlikte, tek bir değişkeni değiştirerek sağdan sola yazılan dilleri işleyen CSS dönüşümlerini kullanarak kaydırılabilir bir yan menü prototipini oluşturduk. Bunu, CSS'de mantıksal özellik dönüşümleri olmadığı ve hiçbir zaman olmayabileceği için yaptık. Elad, mantıksal dönüştürme işlemleri için kendi özel mantığımızın tek bir konumda yönetilmesine olanak tanımak amacıyla yüzdeleri tersine çevirmek için özel bir mülk değeri kullanma fikrini ortaya attı. Bu geçişte aynı tekniği kullandım ve çok başarılı olduğunu düşünüyorum:
.gui-switch {
--isLTR: 1;
&:dir(rtl) {
--isLTR: -1;
}
}
Düzenimiz varsayılan olarak soldan sağa doğru olduğundan --isLTR
adlı özel özellik başlangıçta 1
değerini alır. Bu, true
değerine sahip olduğu anlamına gelir. Ardından, bileşen sağdan sola düzen içinde olduğunda :dir()
CSS sözde sınıfını kullanarak değer -1
olarak ayarlanır.
Bir dönüştürme işleminin içindeki calc()
içinde kullanarak --isLTR
'ü harekete geçirin:
.gui-switch.-vertical > input {
transform: rotate(-90deg);
transform: rotate(calc(90deg * var(--isLTR) * -1));
}
Artık dikey anahtarın döndürülmesi, sağdan sola düzenin gerektirdiği karşı taraf konumu dikkate alır.
Küçük resim öğesi üzerindeki translateX
dönüşümlerinin de karşı taraf şartını dikkate alarak güncellenmesi gerekir:
.gui-switch > input:checked {
--thumb-position: calc(var(--track-size) - 100%);
--thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}
.gui-switch > input:indeterminate {
--thumb-position: calc(
(var(--track-size) / 2) - (var(--thumb-size) / 2)
);
--thumb-position: calc(
((var(--track-size) / 2) - (var(--thumb-size) / 2))
* var(--isLTR)
);
}
Bu yaklaşım, mantıksal CSS dönüştürme işlemleri gibi bir kavramla ilgili tüm ihtiyaçları çözmek için işe yaramasa da birçok kullanım alanı için bazı DRY ilkeleri sunar.
Eyaletler
Yerleşik input[type="checkbox"]
'ü kullanmak için :checked
, :disabled
, :indeterminate
ve :hover
gibi çeşitli durumları ele almak gerekir. :focus
, yalnızca ofsetinde ayarlama yapılarak kasıtlı olarak olduğu gibi bırakıldı. Odak halkası Firefox ve Safari'de harika görünüyordu:
Kontrol edildi
<label for="switch-checked" class="gui-switch">
Default
<input type="checkbox" role="switch" id="switch-checked" checked="true">
</label>
Bu eyalet, on
durumunu temsil eder. Bu durumda, giriş "parça" arka planı etkin renge, başparmak konumu ise "sona" ayarlanır.
.gui-switch > input:checked {
background: var(--track-color-active);
--thumb-position: calc((var(--track-size) - 100%) * var(--isLTR));
}
Devre dışı
<label for="switch-disabled" class="gui-switch">
Default
<input type="checkbox" role="switch" id="switch-disabled" disabled="true">
</label>
:disabled
düğmesi yalnızca görsel olarak farklı görünmekle kalmaz, öğeyi de değiştirilemez hale getirir. Etkileşimin değiştirilemezliği tarayıcıdan bağımsızdır ancak görsel durumların appearance: none
kullanılması nedeniyle stillere ihtiyacı vardır.
.gui-switch > input:disabled {
cursor: not-allowed;
--thumb-color: transparent;
&::before {
cursor: not-allowed;
box-shadow: inset 0 0 0 2px hsl(0 0% 100% / 50%);
@media (prefers-color-scheme: dark) { & {
box-shadow: inset 0 0 0 2px hsl(0 0% 0% / 50%);
}}
}
}
Hem devre dışı hem de işaretli duruma sahip koyu ve açık temalara ihtiyaç duyduğundan bu durum biraz karmaşıktır. Stil kombinasyonlarının bakım yükünü hafifletmek amacıyla bu durumlar için stil olarak minimal stiller seçtim.
Belirsiz
Genellikle unutulan bir durum da :indeterminate
'dir. Bu durumda onay kutusunun işareti kaldırılmamış veya işaretlenmemiştir. Bu eğlenceli bir durum, davet edici ve mütevazı. Boole durumlarının, aralarında gizli durumlar olabileceğini hatırlatmak isteriz.
Onay kutusunu belirsiz olarak ayarlamak zordur. Bu ayarı yalnızca JavaScript yapabilir:
<label for="switch-indeterminate" class="gui-switch">
Indeterminate
<input type="checkbox" role="switch" id="switch-indeterminate">
<script>document.getElementById('switch-indeterminate').indeterminate = true</script>
</label>
Bu eyalet benim için mütevazı ve davetkar olduğundan, anahtar başparmağı konumunu ortada yerleştirmek uygun geldi:
.gui-switch > input:indeterminate {
--thumb-position: calc(
calc(calc(var(--track-size) / 2) - calc(var(--thumb-size) / 2))
* var(--isLTR)
);
}
İmleçle üzerine gelin
Fareyle üzerine gelme etkileşimleri, bağlı kullanıcı arayüzü için görsel destek sağlamalı ve ayrıca etkileşimli kullanıcı arayüzüne yön vermelidir. Bu anahtar, etiket veya giriş üzerine gelindiğinde baş parmağı yarı şeffaf bir halkayla vurgular. Bu fareyle üzerine gelme animasyonu, etkileşimli küçük resim öğesine yönlendirme sağlar.
"Vurgulama" efekti box-shadow
ile yapılır. Fareyle devre dışı bırakılmamış bir girişin üzerine geldiğinizde --highlight-size
boyutunu artırın. Kullanıcı hareketi kabul ediyorsa box-shadow
'ü büyüterek geçiş yaparız. Kullanıcı hareketi kabul etmiyorsa öne çıkan anlar anında gösterilir:
.gui-switch > input::before {
box-shadow: 0 0 0 var(--highlight-size) var(--thumb-color-highlight);
@media (--motionOK) { & {
transition:
transform var(--thumb-transition-duration) ease,
box-shadow .25s ease;
}}
}
.gui-switch > input:not(:disabled):hover::before {
--highlight-size: .5rem;
}
JavaScript
Anahtar arayüzü, fiziksel bir arayüzü taklit etmeye çalışırken (özellikle de bir kanalın içinde daire bulunan bu tür) bana tuhaf gelebilir. iOS, anahtarlarıyla bu konuda doğru bir iş çıkarmış. Anahtarları yana doğru sürükleyebilirsiniz ve bu seçeneğe sahip olmak çok tatmin edici. Buna karşılık, sürükleme hareketi yapılırsa ve hiçbir şey olmazsa kullanıcı arayüzü öğesi etkin olmadığını hissedebilir.
Sürüklenebilir başparmaklar
Küçük resim öğesi, konumunu .gui-switch > input
kapsamlı var(--thumb-position)
öğesinden alır. JavaScript, başparmak konumunu dinamik olarak güncellemek için girişte bir satır içi stil değeri sağlayarak işaretçi hareketini izliyormuş gibi görünmesini sağlayabilir. İşaretçi serbest bırakıldığında satır içi stilleri kaldırın ve özel --thumb-position
özelliğini kullanarak sürüklemenin kapalı mı yoksa açık mı olduğunu belirleyin. Bu, çözümün omurgasıdır; CSS özel özelliklerini değiştirmek için işaretçi konumlarını koşullu olarak izleyen işaretçi etkinlikleri.
Bu komut dosyası gösterilmeden önce bileşen zaten% 100 işlevsel olduğundan, mevcut davranışı sürdürmek için çok fazla çalışma yapılması (girişi değiştirmek için bir etiketi tıklama gibi) yapılması gerekir. JavaScript'imiz, mevcut özelliklerin pahasına yeni özellikler eklememelidir.
touch-action
Sürükleme, touch-action
avantajları için mükemmel bir aday olan özel bir harekettir. Bu geçişte, yatay bir hareket komut dosyamız veya dikey geçiş varyantı için yakalanan dikey bir hareket tarafından gerçekleştirilmelidir. touch-action
ile tarayıcıya bu öğede hangi hareketlerin ele alınacağını söyleyebiliriz. Böylece komut dosyası, hareketi herhangi bir rekabet olmadan işleyebilir.
Aşağıdaki CSS, tarayıcıya bir işaretçi hareketi bu geçiş parçasından başladığında dikey hareketleri işlemesini, yatay hareketlerle hiçbir şey yapmamasını söyler:
.gui-switch > input {
touch-action: pan-y;
}
İstenen sonuç, sayfayı kaydırmayan veya kaydırmayan bir yatay harekettir. İşaretçi, girişten başlayarak dikey olarak kaydırabilir ve sayfayı kaydırabilir ancak yatay olanlar özel olarak işlenir.
Piksel değeri stili yardımcı programları
Kurulum sırasında ve sürükleme sırasında, öğelerden çeşitli hesaplanmış sayı değerlerinin alınması gerekir. Aşağıdaki JavaScript işlevleri, bir CSS özelliğine göre hesaplanmış piksel değerleri döndürür. Bu parametre, getStyle(checkbox, 'padding-left')
gibi kurulum komut dosyasında kullanılır.
const getStyle = (element, prop) => {
return parseInt(window.getComputedStyle(element).getPropertyValue(prop));
}
const getPseudoStyle = (element, prop) => {
return parseInt(window.getComputedStyle(element, ':before').getPropertyValue(prop));
}
export {
getStyle,
getPseudoStyle,
}
window.getComputedStyle()
işlevinin ikinci bir bağımsız değişkeni (hedef sözde öğe) kabul ettiğine dikkat edin. JavaScript'in, sözde öğeler de dahil olmak üzere öğelerden bu kadar çok değeri okuyabilmesi çok kullanışlı.
dragging
Bu, sürükleme mantığı için temel bir andır ve işlev etkinliği işleyicisinden dikkat edilmesi gereken birkaç nokta vardır:
const dragging = event => {
if (!state.activethumb) return
let {thumbsize, bounds, padding} = switches.get(state.activethumb.parentElement)
let directionality = getStyle(state.activethumb, '--isLTR')
let track = (directionality === -1)
? (state.activethumb.clientWidth * -1) + thumbsize + padding
: 0
let pos = Math.round(event.offsetX - thumbsize / 2)
if (pos < bounds.lower) pos = 0
if (pos > bounds.upper) pos = bounds.upper
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
}
Komut dosyası kahramanı state.activethumb
'tir. Bu komut dosyasının bir işaretçiyle birlikte yerleştirdiği küçük dairedir. switches
nesnesi, anahtarların .gui-switch
olduğu ve değerlerin komut dosyasını verimli tutan önbelleğe alınmış sınırlar ve boyutlar olduğu bir Map()
'tır. Sağdan sola akış, CSS'nin kullandığı özel mülk --isLTR
ile yönetilir ve mantığı tersine çevirmek ve RTL'yi desteklemeye devam etmek için kullanılabilir. Başparmak konumlandırması için yararlı bir delta değeri içerdiğinden event.offsetX
de değerlidir.
state.activethumb.style.setProperty('--thumb-position', `${track + pos}px`)
Bu son CSS satırı, küçük resim öğesi tarafından kullanılan özel özelliği ayarlar. Bu değer atama işlemi normalde zaman içinde geçiş yapar ancak önceki bir işaretçi etkinliği --thumb-transition-duration
değerini geçici olarak 0s
olarak ayarlayarak yavaş bir etkileşimi ortadan kaldırır.
dragEnd
Kullanıcının anahtarı çok uzak bir yere sürükleyip bırakmasına izin vermek için küresel bir pencere etkinliği kaydedilmesi gerekir:
window.addEventListener('pointerup', event => {
if (!state.activethumb) return
dragEnd(event)
})
Kullanıcının serbestçe sürükleme özgürlüğüne sahip olması ve arayüzün bunu hesaba katacak kadar akıllı olması çok önemli. Bu geçişle ilgili sorunu çözmek çok fazla zaman almadı ancak geliştirme sürecinde dikkatli bir şekilde ele alınması gerekiyordu.
const dragEnd = event => {
if (!state.activethumb) return
state.activethumb.checked = determineChecked()
if (state.activethumb.indeterminate)
state.activethumb.indeterminate = false
state.activethumb.style.removeProperty('--thumb-transition-duration')
state.activethumb.style.removeProperty('--thumb-position')
state.activethumb.removeEventListener('pointermove', dragging)
state.activethumb = null
padRelease()
}
Öğeyle etkileşim tamamlandı. Giriş kontrollü mülkünü ayarlama ve tüm hareket etkinliklerini kaldırma zamanı. Onay kutusu state.activethumb.checked = determineChecked()
ile değiştirilir.
determineChecked()
dragEnd
tarafından çağrılan bu işlev, baş akımının kanalın sınırları içinde nerede olduğunu belirler ve yol boyunca eşit veya yarısına eşit olduğunda true değerini döndürür:
const determineChecked = () => {
let {bounds} = switches.get(state.activethumb.parentElement)
let curpos =
Math.abs(
parseInt(
state.activethumb.style.getPropertyValue('--thumb-position')))
if (!curpos) {
curpos = state.activethumb.checked
? bounds.lower
: bounds.upper
}
return curpos >= bounds.middle
}
Ek düşünceler
Seçilen ilk HTML yapısı nedeniyle sürükleme hareketi biraz kod borcuna neden oldu. Bu yapının en önemli özelliği, girişin bir etikete sarmalanmasıydı. Ebeveyn öğe olan etiket, girişten sonra tıklama etkileşimlerini alır. dragEnd
etkinliğinin sonunda, padRelease()
işlevinin garip bir şekilde seslendirildiğini fark etmiş olabilirsiniz.
const padRelease = () => {
state.recentlyDragged = true
setTimeout(_ => {
state.recentlyDragged = false
}, 300)
}
Bu, kullanıcının gerçekleştirdiği etkileşimin işaretini kaldıracağı veya işaretleyeceği için etiketin bu sonraki tıklamayı aldığını hesaba katmaktır.
Bunu tekrar yapacak olsaydım, etiket tıklamalarını kendi başına yöneten ve yerleşik davranışla çakışmayan bir öğe oluşturmak için kullanıcı deneyimi yükseltme sırasında DOM'u JavaScript ile ayarlama seçeneğini değerlendirebilirdim.
Bu tür JavaScript'i yazmak en sevmediğim şeylerden biridir. Koşullu etkinlik kabartmayı yönetmek istemiyorum:
const preventBubbles = event => {
if (state.recentlyDragged)
event.preventDefault() && event.stopPropagation()
}
Sonuç
Bu küçük anahtar bileşeni, bugüne kadarki tüm GUI yarışmalarında en çok çalışma gerektiren bileşen oldu. Bunu nasıl yaptığımı öğrendiğinize göre, siz ne yapardınız? 🙂
Gelin, yaklaşımlarımızı çeşitlendirelim ve web'de içerik geliştirmenin tüm yollarını öğrenelim. Bir demo oluşturun, bağlantılarını bana tweetleyin. Ardından, aşağıdaki topluluk remiksleri bölümüne ekleyeceğim.
Topluluk remiksleri
- @KonstantinRouda, özel öğe: demo ve code.
- @jhvanderschee düğmesi: Codepen.
Kaynaklar
.gui-switch
Kaynak kodunu GitHub'da bulun.