Podstawowe informacje o tworzeniu komponentu ustawień z użyciem suwaków i pól wyboru.
W tym poście przedstawię pomysł na opracowanie responsywnego komponentu internetowego, który obsługuje wiele urządzeń wejściowych i działa w różnych przeglądarkach. Zobacz prezentację.
Jeśli wolisz film albo chcesz zobaczyć podgląd UI/UX, co tworzymy, tutaj znajdziesz krótszy przewodnik:
Przegląd
Elementy tego komponentu zostały rozbite na następujące sekcje:
- Układy
- Kolor
- Wprowadzanie zakresu niestandardowego
- Wprowadzanie niestandardowych pól wyboru
- Uwagi na temat ułatwień dostępu
- JavaScript
Układy
To pierwsza prezentacja wyzwania GUI, w którym zastosowano całą siatkę CSS. Oto każda siatka wyróżniona przy użyciu Narzędzi deweloperskich w Chrome dla siatki:
Tylko na przerwę
Najpopularniejszy układ:
foo {
display: grid;
gap: var(--something);
}
Określam ten układ „tylko na potrzeby przerwy”, ponieważ używa on wyłącznie siatki do dodawania odstępów między blokami.
Tej strategii używa się w 5 układach. Oto wszystkie wyświetlane:
Element fieldset
, który zawiera każdą grupę danych wejściowych (.fieldset-item
), używa właściwości gap: 1px
do utworzenia linii brzegowej między elementami. Nie ma skomplikowanego granicznego rozwiązania!
.grid { display: grid; gap: 1px; background: var(--bg-surface-1); & > .fieldset-item { background: var(--bg-surface-2); } }
.grid { display: grid; & > .fieldset-item { background: var(--bg-surface-2); &:not(:last-child) { border-bottom: 1px solid var(--bg-surface-1); } } }
Naturalne zawijanie siatki
Najbardziej złożonym układem był układ makro, czyli logiczny układ od <main>
do <form>
.
Zawijanie treści pośrodku
Flexbox i siatka umożliwiają korzystanie z funkcji align-items
lub align-content
. W przypadku elementów zawijania funkcja wyrównania układu content
rozdziela miejsce między grupy podrzędne.
main {
display: grid;
gap: var(--space-xl);
place-content: center;
}
Główny element korzysta z skrótu wyrównywania place-content: center
, dzięki któremu elementy podrzędne są wyśrodkowane w pionie i w poziomie w układzie z jedną lub dwiema kolumnami.
Obejrzyj film powyżej, aby dowiedzieć się, jak „treść” pozostaje wyśrodkowana, mimo że nastąpiło pakowanie.
Powtórz autodopasowywanie minmax
<form>
używa adaptacyjnego układu siatki dla każdej sekcji.
Układ może się przełączać z jednej do dwóch kolumn w zależności od dostępnego miejsca.
form {
display: grid;
gap: var(--space-xl) var(--space-xxl);
grid-template-columns: repeat(auto-fit, minmax(min(10ch, 100%), 35ch));
align-items: flex-start;
max-width: 89vw;
}
Ta siatka ma inną wartość parametru row-gap
(--space-xl) niż column-gap
(--space-xxl), aby umieścić ten niestandardowy akcent w układzie elastycznym. Podczas tworzenia stosu kolumn
trzeba mieć dużą lukę, ale nie tak dużą, jak na szerokim ekranie.
Właściwość grid-template-columns
wykorzystuje 3 funkcje CSS: repeat()
, minmax()
i min()
. Una Kravets napisała na ten temat świetny post na blogu o układzie RAM.
W naszym układzie są 3 specjalne dodatki, jeśli porównasz go z układem Uny:
- Przekazujemy dodatkową funkcję
min()
. - Określamy wartość
align-items: flex-start
. - Dostępny jest styl
max-width: 89vw
.
Dodatkową funkcję min()
dobrze opisuje Evan Minto na swoim blogu w poście Intrinsically profil CSS Grid with minmax() i min(). Warto go przeczytać. Korekta wyrównania flex-start
usuwa domyślny efekt rozciągania. Dzięki temu elementy podrzędne tego układu nie muszą mieć równych wysokości, ale mogą mieć naturalne, naturalne wysokości. W filmie w YouTube pokrótce przedstawiliśmy tę kwestię.
W tym poście zebraliśmy krótkie podsumowanie dla kategorii max-width: 89vw
.
Pokażę Ci układ z zastosowanym stylem i bez niego:
Co się dzieje? Jeśli jest określony max-width
, podaje dla algorytmu układu auto-fit
kontekst, jasno określony lub nieokreślony rozmiar, aby ustalić, ile powtórzeń może się zmieścić w przestrzeni. Wydaje się oczywiste, że przestrzeń ma pełną szerokość, ale zgodnie ze specyfikacją siatki CSS należy podać konkretny rozmiar lub maksymalny rozmiar. Podałem rozmiar maksymalny.
Dlaczego 89vw
? Ponieważ „pomogło” w moim układzie.
Ja i kilka innych osób z Chrome badamy, dlaczego bardziej uzasadniona wartość, np. 100vw
, jest niewystarczająca i czy w rzeczywistości to jest błąd.
Odstępy
Większość harmonii tego układu wynika z ograniczonej palety odstępów (dokładnie 7).
:root {
--space-xxs: .25rem;
--space-xs: .5rem;
--space-sm: 1rem;
--space-md: 1.5rem;
--space-lg: 2rem;
--space-xl: 3rem;
--space-xxl: 6rem;
}
Układy te działają bardzo dobrze dzięki siatce, @nest i składni @media na poziomie 5. Oto przykład obejmujący pełny zestaw stylów (<main>
).
main {
display: grid;
gap: var(--space-xl);
place-content: center;
padding: var(--space-sm);
@media (width >= 540px) {
& {
padding: var(--space-lg);
}
}
@media (width >= 800px) {
& {
padding: var(--space-xl);
}
}
}
Siatka z wyśrodkowaną treścią, domyślnie z umiarkowaną dopełnieniem (jak na urządzeniu mobilnym). W miarę pojawiania się coraz większej ilości widocznego obszaru rozszerzają się one, zwiększając dopełnienie. CSS na 2021 rok wygląda całkiem nieźle
Pamiętasz poprzedni układ, „tylko na wypadek przerwy”? Oto dokładniejsza wersja wyglądu w tym komponencie:
header {
display: grid;
gap: var(--space-xxs);
}
section {
display: grid;
gap: var(--space-md);
}
Kolor
Kontrolowane użycie kolorów pozwoliło sprawić, by projekt wyróżniał się jako ekspresyjny, a jednocześnie minimalny. Zrobię to w ten sposób:
:root {
--surface1: lch(10 0 0);
--surface2: lch(15 0 0);
--surface3: lch(20 0 0);
--surface4: lch(25 0 0);
--text1: lch(95 0 0);
--text2: lch(75 0 0);
}
Kolory powierzchni i tekstu nazywam liczbami, a nie nazwami takimi jak surface-dark
czy surface-darker
. W zapytaniu o multimedia zostaną one odwrócone, a kolory jasne i ciemne nie będą miały znaczenia.
Odwracam je w zapytaniu o media w ten sposób:
:root {
...
@media (prefers-color-scheme: light) {
& {
--surface1: lch(90 0 0);
--surface2: lch(100 0 0);
--surface3: lch(98 0 0);
--surface4: lch(85 0 0);
--text1: lch(20 0 0);
--text2: lch(40 0 0);
}
}
}
Ważne jest, by uzyskać szybki rzut oka na ogólny obraz i strategię, zanim przejdziemy do szczegółów składni kolorów. Wyprzedziłem się trochę, więc wrócę jeszcze raz.
LCH?
Nie zagłębimy się zbytnio w teorię kolorów, więc LCH to składnia zorientowana na ludzi, która uwzględnia sposób postrzegania koloru, a nie sposób pomiaru kolorów za pomocą matematyki (np. 255). Zapewnia to wyraźną przewagę, ponieważ ludzie mogą łatwiej pisać, a inni dostosowują się do tych zmian.
![Zrzut ekranu strony pod.link/csspodcast z wyświetlonym odcinkiem Kolor 2: Percepcja](https://web.dev/static/articles/building/a-settings-component/image/a-screenshot-podlinkcs-a40f130bf81b8.png?authuser=7&hl=pl)
Dzisiaj skoncentruję się na składni i wartościach, które zmieniam, aby ustawić jasne i ciemne kolory. Przyjrzyjmy się 1 płaszczyźnie i 1 kolorowi tekstu:
:root {
--surface1: lch(10 0 0);
--text1: lch(95 0 0);
@media (prefers-color-scheme: light) {
& {
--surface1: lch(90 0 0);
--text1: lch(40 0 0);
}
}
}
--surface1: lch(10 0 0)
oznacza jasność 10%
, 0 kolorów i 0 odcieni: bardzo ciemną, bezbarwną szarość. Następnie w zapytaniu o tryb jasny kolor jest zmieniany na 90%
za pomocą funkcji --surface1: lch(90 0 0);
. To jest sedno strategii. Zacznij od zmiany jasności między 2 motywami, zachowania współczynników kontrastu oczekiwanych przez projekt lub elementów przystępnych.
Dodatkową zaletą lch()
jest to, że światło jest związane z człowiekiem. Możemy się poczuć pozytywnie po wprowadzeniu zmiany w elemencie %
, która będzie postrzegana jako %
odmienna i spójna. Na przykład hsl()
nie jest tak wiarygodne.
Dowiedz się więcej o przestrzennych kolorach i lch()
, jeśli Cię zainteresują. Już wkrótce!
Usługa porównywania cen w ogóle nie może uzyskać dostępu do tych kolorów. Powtórzę: większość nowoczesnych monitorów nie ma dostępu do jednej trzeciej kolorów. Nie chodzi tylko o żadne kolory, ale o najżywsze kolory, jakie może wyświetlić ekran. Nasze strony internetowe są niepełne, ponieważ sprzęt monitorujący ewoluował szybciej niż specyfikacje CSS i implementacje przeglądarek.
Lea Verou
Adaptacyjne elementy sterujące formularzem oparte na schemacie kolorów
Wiele przeglądarek udostępnia elementy sterujące ciemnego motywu (obecnie Safari i Chromium), ale w kodzie CSS lub HTML musisz wskazać, że mają być one używane w Twoim projekcie.
Powyżej pokazujemy efekt właściwości z panelu Style w Narzędziach deweloperskich. Prezentacja używa tagu HTML, który moim zdaniem jest lepszym miejscem:
<meta name="color-scheme" content="dark light">
Wszystkiego na ten temat dowiesz się z color-scheme
artykułu Thomasa Steinera. Możesz zyskać o wiele więcej niż
wpisane ciemne pola wyboru.
Usługa porównywania cen accent-color
Ostatnio zauważyliśmy aktywność w obszarze accent-color
elementów formularza, który jest pojedynczym stylem CSS, który może zmieniać kolor odcienia w elementach wejściowych przeglądarki. Więcej informacji na ten temat znajdziesz tutaj na GitHubie. Umieściłam go w stylach tego komponentu. W miarę jak przeglądarki ją obsługują, pola wyboru będą zawierać wyostrzenie różowo-fioletowe.
input[type="checkbox"] {
accent-color: var(--brand);
}
Wyostrzenie kolorów ze stałymi gradientami i skupieniem
Kolory wyostrzeją się najlepiej, gdy używam ich niewiele. Jednym ze sposobów na osiągnięcie tego celu są kolorowe interakcje w interfejsie.
W powyższym filmie ma wiele warstw opinii i interakcji z interfejsem, które pozwalają nadać interakcjom osobisty charakter:
- Podkreślenie kontekstu.
- Przekazuje w interfejsie informacje zwrotne o tym, jak pełna wartość mieści się w zakresie.
- Przekazywanie informacji o tym, że pole akceptuje dane wejściowe.
Aby dostarczyć informacje zwrotne o interakcji z elementem, CSS korzysta z :focus-within
pseudoklasy do zmiany wyglądu różnych elementów. Przyjrzyjmy się następującym opcjom:
.fieldset-item
, jest to niezwykle interesujące:
.fieldset-item {
...
&:focus-within {
background: var(--surface2);
& svg {
fill: white;
}
& picture {
clip-path: circle(50%);
background: var(--brand-bg-gradient) fixed;
}
}
}
Gdy jedno z elementów podrzędnych tego elementu jest aktywne:
- Do tła
.fieldset-item
przypisano wyższy kontrastowy kolor powierzchni. - Zagnieżdżony element
svg
jest wypełniany na biało, aby zwiększyć kontrast. - Zagnieżdżony element
<picture>
clip-path
rozwija się do pełnego okręgu, a tło jest wypełnione jasnym, stałym gradientem.
Zakres niestandardowy
Biorąc pod uwagę ten element wprowadzania HTML, pokażę Ci, jak dostosowałem jego wygląd:
<input type="range">
Ten element składa się z 3 części:
Style elementów zakresu
input[type="range"] {
/* style setting variables */
--track-height: .5ex;
--track-fill: 0%;
--thumb-size: 3ex;
--thumb-offset: -1.25ex;
--thumb-highlight-size: 0px;
appearance: none; /* clear styles, make way for mine */
display: block;
inline-size: 100%; /* fill container */
margin: 1ex 0; /* ensure thumb isn't colliding with sibling content */
background: transparent; /* bg is in the track */
outline-offset: 5px; /* focus styles have space */
}
Pierwsze kilka wierszy kodu CSS to niestandardowe części stylów. Mam nadzieję, że ich jasne oznaczenie w tym pomoże. Pozostałe style to głównie style zresetowane, aby zapewnić spójne podstawy do budowania trudnych części komponentu.
Śledź style
input[type="range"]::-webkit-slider-runnable-track {
appearance: none; /* clear styles, make way for mine */
block-size: var(--track-height);
border-radius: 5ex;
background:
/* hard stop gradient:
- half transparent (where colorful fill we be)
- half dark track fill
- 1st background image is on top
*/
linear-gradient(
to right,
transparent var(--track-fill),
var(--surface1) 0%
),
/* colorful fill effect, behind track surface fill */
var(--brand-bg-gradient) fixed;
}
Kluczem do sukcesu jest „odkrycie” żywych kolorów wypełnienia. Odbywa się to za pomocą gradientu ostrego stopu na górze. Gradient jest przezroczysty do określonego procentu wypełnienia, a potem stosowany jest niewypełniony kolor powierzchni ścieżki. Za niewypełnioną powierzchnią znajduje się kolor pełnej szerokości, który przezroczystość go odkrywa.
Śledź styl wypełnienia
Mój projekt wymaga JavaScriptu do zachowania stylu wypełnienia. Istnieją strategie dotyczące tylko CSS, ale wymagają one, by element kciuka miał tę samą wysokość co utwór. Nie udało mi się znaleźć harmonii w tych limitach.
/* grab sliders on page */
const sliders = document.querySelectorAll('input[type="range"]')
/* take a slider element, return a percentage string for use in CSS */
const rangeToPercent = slider => {
const max = slider.getAttribute('max') || 10;
const percent = slider.value / max * 100;
return `${parseInt(percent)}%`;
};
/* on page load, set the fill amount */
sliders.forEach(slider => {
slider.style.setProperty('--track-fill', rangeToPercent(slider));
/* when a slider changes, update the fill prop */
slider.addEventListener('input', e => {
e.target.style.setProperty('--track-fill', rangeToPercent(e.target));
})
})
Wydaje mi się, że warto to zmienić na lepsze. Suwak działa świetnie bez JavaScriptu, właściwość --track-fill
nie jest wymagana i po prostu nie będzie mieć stylu wypełnienia. Jeśli masz dostęp do JavaScriptu, wypełnij właściwość niestandardową, obserwując też zmiany wprowadzane przez użytkowników i synchronizując ją z wartością.
Oto świetny post na temat CSS-Tricks autorstwa Any Tudor, w którym prezentujemy rozwiązanie wykorzystujące wyłącznie CSS do wypełniania ścieżki. Uważam też, że ten element range
jest bardzo inspirujący.
Style miniatur
input[type="range"]::-webkit-slider-thumb {
appearance: none; /* clear styles, make way for mine */
cursor: ew-resize; /* cursor style to support drag direction */
border: 3px solid var(--surface3);
block-size: var(--thumb-size);
inline-size: var(--thumb-size);
margin-top: var(--thumb-offset);
border-radius: 50%;
background: var(--brand-bg-gradient) fixed;
}
Większość tych stylów ma służyć do utworzenia ładnego okręgu.
Jak widać, widzimy stały gradient tła, który ujednolica dynamiczne kolory kciuków, ścieżek i powiązanych elementów SVG.
Rozdzieliłem style interakcji, aby wyodrębnić metodę box-shadow
wykorzystywaną podczas najeżdżania kursorem:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
::-webkit-slider-thumb {
…
/* shadow spread is initally 0 */
box-shadow: 0 0 0 var(--thumb-highlight-size) var(--thumb-highlight-color);
/* if motion is OK, transition the box-shadow change */
@media (--motionOK) {
& {
transition: box-shadow .1s ease;
}
}
/* on hover/active state of parent, increase size prop */
@nest input[type="range"]:is(:hover,:active) & {
--thumb-highlight-size: 10px;
}
}
Celem było łatwe zarządzanie i wizualne wyróżnienie ich opinii. Używając cienia ramki, mogę uniknąć uruchamiania układu. Robię to, tworząc cień, który nie jest rozmyty i pasuje do okrągłego kształtu kciuka. Następnie zmieniam jego rozmiar i przenoszę go, gdy najedziemy na niego kursorem.
Gdyby tylko efekt zaznaczenia był tak łatwy przy polach wyboru...
Selektory różnych przeglądarek
Aby zachować spójność w różnych przeglądarkach, potrzebuję tych selektorów -webkit-
i -moz-
:
input[type="range"] {
&::-webkit-slider-runnable-track {}
&::-moz-range-track {}
&::-webkit-slider-thumb {}
&::-moz-range-thumb {}
}
Niestandardowe pole wyboru
Biorąc pod uwagę ten element wprowadzania HTML, pokażę Ci, jak dostosowałem jego wygląd:
<input type="checkbox">
Ten element składa się z 3 części:
Element pola wyboru
input[type="checkbox"] {
inline-size: var(--space-sm); /* increase width */
block-size: var(--space-sm); /* increase height */
outline-offset: 5px; /* focus style enhancement */
accent-color: var(--brand); /* tint the input */
position: relative; /* prepare for an absolute pseudo element */
transform-style: preserve-3d; /* create a 3d z-space stacking context */
margin: 0;
cursor: pointer;
}
Style transform-style
i position
przygotowują się do pseudoelementu, który omówimy później, by określić styl zaznaczenia. Poza tym są to głównie moje
opinie o stylu. Lubię, gdy kursor jest wskaźnikiem. Podoba mi się
przesunięcia konturu, domyślne pola wyboru są za małe, a jeśli accent-color
jest obsługiwany, umieść te pola wyboru w schemacie kolorów marki.
Etykiety pól wyboru
Etykiety pól wyboru są ważne z 2 powodów. Pierwszy z nich to określenie, do czego służy wartość pola wyboru, czyli odpowiedź „po co włączać i wyłączać?” Po drugie z myślą o UX użytkownicy internetu przyzwyczaili się do interakcji z polami wyboru za pomocą powiązanych z nimi etykiet.
<input type="checkbox" id="text-notifications" name="text-notifications" >
<label for="text-notifications"> <h3>Text Messages</h3> <small>Get notified about all text messages sent to your device</small> </label>
Umieść na etykiecie atrybut for
wskazujący pole wyboru o identyfikatorze: <label for="text-notifications">
. W polu wyboru podwaj zarówno nazwę, jak i identyfikator, aby mieć pewność, że zostaną znalezione za pomocą różnych narzędzi i technologii, takich jak mysz lub czytnik ekranu: <input type="checkbox" id="text-notifications" name="text-notifications">
.
:hover
, :active
i inne aplikacje są dostępne bezpłatnie w przypadku połączenia, co zwiększa możliwości interakcji z formularzem.
Wyróżnienie pola wyboru
Zależy mi na tym, by interfejs był spójny, a suwak ma ładne podświetlenie miniatur, które chcę dodać do tego pola wyboru. Miniatura mogła korzystać z atrybutu box-shadow
i właściwości spread
, która umożliwia skalowanie cienia w górę i w dół. Ten efekt nie działa jednak w tym przypadku, ponieważ nasze pola wyboru są i powinny być kwadratowe.
Udało mi się uzyskać ten sam efekt wizualny za pomocą pseudoelementu i nieprawdziwą liczbę podchwytliwych elementów CSS:
@custom-media --motionOK (prefers-reduced-motion: no-preference);
input[type="checkbox"]::before {
--thumb-scale: .01; /* initial scale of highlight */
--thumb-highlight-size: var(--space-xl);
content: "";
inline-size: var(--thumb-highlight-size);
block-size: var(--thumb-highlight-size);
clip-path: circle(50%); /* circle shape */
position: absolute; /* this is why position relative on parent */
top: 50%; /* pop and plop technique (https://web.dev/centering-in-css#5-pop-and-plop) */
left: 50%;
background: var(--thumb-highlight-color);
transform-origin: center center; /* goal is a centered scaling circle */
transform: /* order here matters!! */
translateX(-50%) /* counter balances left: 50% */
translateY(-50%) /* counter balances top: 50% */
translateZ(-1px) /* PUTS IT BEHIND THE CHECKBOX */
scale(var(--thumb-scale)) /* value we toggle for animation */
;
will-change: transform;
@media (--motionOK) { /* transition only if motion is OK */
& {
transition: transform .2s ease;
}
}
}
/* on hover, set scale custom property to "in" state */
input[type="checkbox"]:hover::before {
--thumb-scale: 1;
}
Utworzenie pseudoelementu koła to prosta praca, ale trudniejsze jest umieszczenie go za elementem, do którego jest przyłączony. Zobacz, co zrobię przed i po naprawieniu:
To bez wątpienia mikrointerakcja, ale dla mnie ważna
jest zachowanie spójności wizualnej. Technika skalowania animacji jest taka sama jak w innych miejscach. Nadajemy właściwości niestandardowej nową wartość i pozwalamy CSS przenieść ją w zależności od preferencji ruchu. Kluczową funkcją jest translateZ(-1px)
. Stworzyła przestrzeń 3D, a to pseudoelementowe dziecko skorzystało z niej, odsuwając się trochę z powrotem w miejsce na osi Z.
Ułatwienia dostępu
Film w YouTube doskonale demonstruje działanie myszy, klawiatury i czytnika ekranu w przypadku tego komponentu ustawień. Postaram się zwrócić uwagę na niektóre szczegóły.
Opcje elementów HTML
<form>
<header>
<fieldset>
<picture>
<label>
<input>
Każda z nich zawiera wskazówki i wskazówki dotyczące narzędzia do przeglądania internetu. Niektóre elementy zawierają wskazówki dotyczące interakcji, inne umożliwiają interakcję, a jeszcze inne pomagają kształtować drzewo ułatwień dostępu, po którym porusza się czytnik ekranu.
Atrybuty HTML
Możemy ukryć elementy, których nie potrzebują czytniki ekranu. W tym przypadku widać ikonę obok suwaka:
<picture aria-hidden="true">
Film powyżej pokazuje działanie czytnika ekranu w systemie macOS. Zwróć uwagę, jak fokus przenosi się bezpośrednio z jednego suwaka do następnego. Dzieje się tak, ponieważ ukryliśmy ikonę, która nie pozwalała na przejście do następnego suwaka. Bez tego atrybutu użytkownik musiałby zatrzymać się, słuchać i mijać obraz, którego być może nie może zobaczyć.
SVG to działanie matematyczne. Dodajmy element <title>
z tytułem bezpłatnego najechania kursorem myszy i zrozumiałym dla człowieka komentarzem na temat tego, co generuje matematyka:
<svg viewBox="0 0 24 24">
<title>A note icon</title>
<path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/>
</svg>
Poza tym użyjemy wystarczająco wyraźnie oznaczonego języka HTML, by formularz bardzo dobrze sprawdzał się przy użyciu myszy, klawiatury, kontrolerów do gier i czytników ekranu.
JavaScript
Omówiłem już sposób zarządzania kolorem wypełnienia ścieżki w JavaScript. Spójrzmy teraz na powiązany z <form>
skrypt JavaScriptu:
const form = document.querySelector('form');
form.addEventListener('input', event => {
const formData = Object.fromEntries(new FormData(form));
console.table(formData);
})
Za każdym razem, gdy użytkownik wchodzi w interakcję z formularzem i zmienia go, konsola zapisuje go jako obiekt w tabeli, aby można go było łatwo przejrzeć przed przesłaniem go na serwer.
Podsumowanie
Skoro już wiesz, jak to udało mi się osiągnąć, to jak? W ten sposób powstaje zabawna architektura komponentów. Kto utworzy pierwszą wersję z boksami w swojej ulubionej platformie? 🙂
Stwórzmy różne metody i nauczmy się wszystkiego, jak rozwijać się w internecie. Utwórz demonstrację i udostępnij mi linki na Twitterze, a dodam ją do sekcji Remiksy społeczności poniżej.