fa
Feedback
Glo Academy

Glo Academy

رفتن به کانال در Telegram

Бесплатные уроки по HTML/CSS/JavaScript, лайфхаки для верстальщика и бесплатные дизайн-макеты для портфолио. По рекламе — @yankovsky_ads Купить рекламу напрямую https://telega.in/c/glo_academy

نمایش بیشتر
3 772
مشترکین
-124 ساعت
-77 روز
-4130 روز
جذب مشترکین
سپتامبر '26
سپتامبر '26
+4
در 0 کانال‌ها
اوت '26
+35
در 1 کانال‌ها
Get PRO
ژوئیه '26
+6
در 0 کانال‌ها
Get PRO
ژوئن '26
+5
در 0 کانال‌ها
Get PRO
مه '26
+9
در 0 کانال‌ها
Get PRO
آوریل '26
+14
در 0 کانال‌ها
Get PRO
مارس '26
+11
در 0 کانال‌ها
Get PRO
فوریه '26
+23
در 0 کانال‌ها
Get PRO
ژانویه '26
+8
در 0 کانال‌ها
Get PRO
دسامبر '25
+15
در 0 کانال‌ها
Get PRO
نوامبر '25
+16
در 0 کانال‌ها
Get PRO
اکتبر '25
+10
در 0 کانال‌ها
Get PRO
سپتامبر '25
+19
در 0 کانال‌ها
Get PRO
اوت '25
+16
در 0 کانال‌ها
Get PRO
ژوئیه '25
+19
در 0 کانال‌ها
Get PRO
ژوئن '25
+10
در 0 کانال‌ها
Get PRO
مه '25
+13
در 0 کانال‌ها
Get PRO
آوریل '25
+17
در 0 کانال‌ها
Get PRO
مارس '25
+20
در 0 کانال‌ها
Get PRO
فوریه '25
+19
در 0 کانال‌ها
Get PRO
ژانویه '25
+16
در 0 کانال‌ها
Get PRO
دسامبر '24
+35
در 0 کانال‌ها
Get PRO
نوامبر '24
+25
در 0 کانال‌ها
Get PRO
اکتبر '24
+32
در 0 کانال‌ها
Get PRO
سپتامبر '24
+43
در 0 کانال‌ها
Get PRO
اوت '24
+52
در 0 کانال‌ها
Get PRO
ژوئیه '24
+49
در 0 کانال‌ها
Get PRO
ژوئن '24
+40
در 0 کانال‌ها
Get PRO
مه '24
+30
در 0 کانال‌ها
Get PRO
آوریل '24
+42
در 0 کانال‌ها
Get PRO
مارس '24
+44
در 0 کانال‌ها
Get PRO
فوریه '24
+47
در 0 کانال‌ها
Get PRO
ژانویه '24
+43
در 0 کانال‌ها
Get PRO
دسامبر '23
+55
در 0 کانال‌ها
Get PRO
نوامبر '23
+65
در 0 کانال‌ها
Get PRO
اکتبر '23
+50
در 0 کانال‌ها
Get PRO
سپتامبر '23
+41
در 0 کانال‌ها
Get PRO
اوت '23
+72
در 0 کانال‌ها
Get PRO
ژوئیه '23
+74
در 0 کانال‌ها
Get PRO
ژوئن '23
+37
در 0 کانال‌ها
Get PRO
مه '23
+85
در 0 کانال‌ها
Get PRO
آوریل '23
+71
در 0 کانال‌ها
Get PRO
مارس '23
+49
در 0 کانال‌ها
Get PRO
فوریه '23
+67
در 0 کانال‌ها
Get PRO
ژانویه '23
+51
در 0 کانال‌ها
Get PRO
دسامبر '22
+59
در 0 کانال‌ها
Get PRO
نوامبر '22
+102
در 0 کانال‌ها
Get PRO
اکتبر '22
+63
در 0 کانال‌ها
Get PRO
سپتامبر '22
+57
در 0 کانال‌ها
Get PRO
اوت '22
+103
در 0 کانال‌ها
Get PRO
ژوئیه '22
+64
در 0 کانال‌ها
Get PRO
ژوئن '22
+63
در 0 کانال‌ها
Get PRO
مه '22
+50
در 0 کانال‌ها
Get PRO
آوریل '22
+93
در 0 کانال‌ها
Get PRO
مارس '22
+82
در 0 کانال‌ها
Get PRO
فوریه '22
+46
در 0 کانال‌ها
Get PRO
ژانویه '22
+75
در 0 کانال‌ها
Get PRO
دسامبر '21
+76
در 0 کانال‌ها
Get PRO
نوامبر '21
+110
در 0 کانال‌ها
Get PRO
اکتبر '21
+123
در 0 کانال‌ها
Get PRO
سپتامبر '21
+99
در 0 کانال‌ها
Get PRO
اوت '21
+139
در 0 کانال‌ها
Get PRO
ژوئیه '21
+149
در 0 کانال‌ها
Get PRO
ژوئن '21
+224
در 0 کانال‌ها
Get PRO
مه '21
+183
در 0 کانال‌ها
Get PRO
آوریل '21
+190
در 0 کانال‌ها
Get PRO
مارس '21
+263
در 0 کانال‌ها
Get PRO
فوریه '21
+290
در 0 کانال‌ها
Get PRO
ژانویه '21
+477
در 0 کانال‌ها
Get PRO
دسامبر '20
+7 655
در 0 کانال‌ها
تاریخ
رشد مشترکین
اشارات
کانال‌ها
18 سپتامبر0
17 سپتامبر+1
16 سپتامبر0
15 سپتامبر0
14 سپتامبر0
13 سپتامبر0
12 سپتامبر0
11 سپتامبر0
10 سپتامبر+2
09 سپتامبر0
08 سپتامبر0
07 سپتامبر0
06 سپتامبر+1
05 سپتامبر0
04 سپتامبر0
03 سپتامبر0
02 سپتامبر0
01 سپتامبر0
پست‌های کانال
Таймаут для fetch без setTimeout Таймаут для fetch обычно собирают из трёх частей: AbortController, setTimeout, который дёргает abort(), и clearTimeout в finally.
try {
  const res = await fetch(url, {
    signal: AbortSignal.timeout(5000)
  });
  const data = await res.json();
} catch (err) {
  if (err.name === 'TimeoutError') {
    // ответа нет 5 секунд
  }
}
AbortSignal.timeout(5000) создаёт сигнал, который сам сработает через 5 секунд. Передаёшь его в fetch как обычный signal, таймер живёт внутри сигнала, чистить его в finally не нужно. Ошибка приходит с именем TimeoutError, а не AbortError — по нему в catch отличаешь «сервер не ответил» от «пользователь отменил». Таймер не останавливается после первого await. Если сервер прислал заголовки, а тело отдаёт по капле, то res.json() тоже упадёт с TimeoutError, когда 5 секунд истекут. Отдельный таймаут на чтение ответа ставить не нужно. Работает в Chrome с 124-й версии, Firefox со 100-й, Safari с 16-й. 🔥 — если было полезно @glo_academy | #js_day

2
🧰 NumberFlow Цена в калькуляторе тарифа меняется рывком: было 199, стало 249, и глаз не успевает понять, что произошло. Обыч
🧰 NumberFlow Цена в калькуляторе тарифа меняется рывком: было 199, стало 249, и глаз не успевает понять, что произошло. Обычно либо оставляют как есть, либо пишут свой счётчик на setInterval, который перебирает числа по одному. NumberFlow крутит каждый разряд отдельно, как барабан механического счётчика: в 199 → 249 сотни поднимаются на единицу, десятки прокручиваются с 9 на 4, последняя девятка стоит на месте. Форматирование через Intl.NumberFormat: валюта, разделители тысяч, суффикс вроде «/мес» встают сами, а когда разрядов становится больше, новая цифра выезжает, старая гаснет. На ролике слева обычная подмена, справа NumberFlow. Без зависимостей, есть пакеты под React, Vue, Svelte и веб-компонент для чистого JS: flow.update(249) — и всё. Уважает prefers-reduced-motion; в старых браузерах без mod() и linear() число просто подменяется, без анимации. https://github.com/barvian/number-flow 🔥 — если было полезно @glo_academy | #инструменты
168
3
Так или не так, скажите? 😂 @glo_academy
Так или не так, скажите? 😂 @glo_academy
218
4
✂️ Длинное название не растягивает карточку Название товара на три строки — и кнопки «В корзину» в ряду встают на разной высо
✂️ Длинное название не растягивает карточку Название товара на три строки — и кнопки «В корзину» в ряду встают на разной высоте. В JS обрезают по числу символов, но буквы разной ширины: где-то оборвёт на полуслове, где-то не влезет. CSS режет по ширине блока: /* одна строка */ .title { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } /* три строки */ .desc { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; } Одна строка: nowrap запрещает перенос, hidden прячет хвост, ellipsis дорисовывает многоточие. Несколько строк: -webkit-line-clamp задаёт, сколько оставить; соседние три строки обязательны. На гифке: без обрезки карточки в ряду разной высоты, с обрезкой — ровные. Однострочному варианту нужна ширина у элемента или родителя. В разметке текст целиком, поиск его найдёт. Префикс -webkit- обязателен: без него line-clamp понимает только Safari 18.2+. ❤️ — если понравился пост @glo_academy | #snippets
236
5
🎨 Колонки едут в противоположные стороны при скролле Три колонки карточек: при прокрутке крайние уезжают вверх, средняя — вн
🎨 Колонки едут в противоположные стороны при скролле Три колонки карточек: при прокрутке крайние уезжают вверх, средняя — вниз. Раньше это делали слушателем scroll и transform в JS, теперь хватает CSS: .col { animation: up linear both; animation-timeline: view(); animation-range: entry 0% cover 100%; } .col:nth-child(2) { animation-name: down; } @keyframes up { to { translate: 0 -30% } } @keyframes down { to { translate: 0 30% } } view() привязывает анимацию к положению колонки на экране: проехала колонка — продвинулись кадры. animation-range задаёт участок: от появления снизу (entry 0%) до ухода за верхний край (cover 100%). В @keyframes крайние колонки едут на 30% высоты вверх, средняя — вниз. На гифке ползунок справа — положение скролла, колонки едут за ним. Обработчика scroll и расчётов на кадр нет. animation-timeline ставь после шорткода animation, иначе он его сбросит. Chrome 115+, Safari 26+, Firefox пока Nightly — оборачивай в @supports. 🔥 — если было полезно @glo_academy | #css_day
269
6
📐 Лендинг туристической страховки Макет средней сложности с адаптивом на русском языке @glo_academy | #макеты
📐 Лендинг туристической страховки Макет средней сложности с адаптивом на русском языке @glo_academy | #макеты
327
7
⚡ Node распаковывает ZIP без сторонних библиотек Раньше zip в Node открывали пакетом — adm-zip или unzipper. С Node 26.8 это
⚡ Node распаковывает ZIP без сторонних библиотек Раньше zip в Node открывали пакетом — adm-zip или unzipper. С Node 26.8 это умеет сам node:zlib. import { ZipBuffer } from 'node:zlib'; import { readFileSync, writeFileSync } from 'node:fs'; const zip = new ZipBuffer(readFileSync('archive.zip')); for (const [name, entry] of zip) console.log(name, entry.size); await zip.add('readme.txt', Buffer.from('Привет')); zip.delete('draft.txt'); writeFileSync('archive.zip', await zip.toBuffer()); Конструктор берёт архив буфером и даёт перебирать записи. add кладёт файл, delete убирает, toBuffer собирает архив заново. Главный выигрыш — память. adm-zip читает архив целиком, ZipBuffer берёт записи по одной прямо из буфера, а ZipFile.stream() отдаёт запись потоком. В maxSize ставишь предел на распакованный размер: архив на пару килобайт, разворачивающийся в гигабайты, дальше лимита не пойдёт. Фича экспериментальная и пока только в 26-й ветке: LTS она станет 28 октября. 🔥 — если было полезно @glo_academy | #js_day
368
8
Акция ко Дню рождения Glo Academy стартовала 🎉 Пару дней назад школе исполнилось 10 лет — по этому поводу принимаем поздравл
Акция ко Дню рождения Glo Academy стартовала 🎉 Пару дней назад школе исполнилось 10 лет — по этому поводу принимаем поздравления и проводим большую акцию, которая продлится до 14 сентября В ней участвуют наши основные курсы. На каждый из них можно записаться с большой скидкой В списке появились новые программы: по Vue, React + Next, TypeScript и большой обновленный курс Фуллстек-разработчик Есть рассрочка до 12 месяцев для нескольких стран, а также промокод ДР10, который даст дополнительные приятные условия Все детали — на странице акции: 👉Выбрать курс https://glo.academy/bday/ А в тг-канале проведем отдельный розыгрыш среди участников акции, подключайтесь: https://t.me/+lMQho8IDDTo2ZDZi
401
9
🧰 swup Между страницами обычного сайта белая вспышка: браузер выгружает одну и рисует другую с нуля. Ради плавности проекты
🧰 swup Между страницами обычного сайта белая вспышка: браузер выгружает одну и рисует другую с нуля. Ради плавности проекты переезжают на SPA и получают в нагрузку роутер, состояние и гидратацию. swup перехватывает клик по ссылке, подгружает следующую страницу и подменяет только контейнер с контентом, а смену анимирует обычным CSS-переходом. Бэкенд любой: PHP, Django, статика из папки. На ролике слева обычный переход, справа он же через swup. Плагины добавляют прогресс-бар, предзагрузку ссылки под курсором и анимацию отправки форм. Опция native: true переводит анимацию на встроенный в браузер View Transitions API там, где он есть. Версия 4.10 вышла на прошлой неделе. https://github.com/swup/swup 🔥 — если было полезно @glo_academy | #инструменты
352
10
Блочная модель на собаках @glo_academy
Блочная модель на собаках @glo_academy
357
11
✂️ Поле телефона открывает цифровую клавиатуру Открываешь форму на телефоне, тапаешь в поле для номера — и вылезает буквенная
✂️ Поле телефона открывает цифровую клавиатуру Открываешь форму на телефоне, тапаешь в поле для номера — и вылезает буквенная клавиатура. Человек жмёт «123», ищет плюс, промахивается по цифрам. На этом месте формы и бросают. <label> Телефон <input type="tel" inputmode="tel"> </label> <label> Индекс <input type="text" inputmode="numeric"> </label> За клавиатуру отвечает отдельный атрибут — inputmode. type говорит браузеру, какие данные в поле и как их проверять, а inputmode — только какую клавиатуру открыть на мобильном. Поэтому их ставят вместе: type="tel" inputmode="tel", и человек видит телефонную клавиатуру вместо букв. Ещё есть numeric, decimal, email, url и search. Для индекса, кода из смс и номера карты бери type="text" с inputmode="numeric": у type="number" сбоку стрелки-спиннеры, а ведущие нули он съедает — индекс 01234 станет 1234. ❤️ — если полезно @glo_academy | #snippets
388
12
🎨 Выравниваем текст без Заголовок в макете смотрелся ровно, а в браузере последнее слово повисло одно на второй строке.
🎨 Выравниваем текст без <br> Заголовок в макете смотрелся ровно, а в браузере последнее слово повисло одно на второй строке. Обычно это лечат руками: ставят <br> в нужном месте или склеивают два последних слова через &nbsp;. Держится до первой правки текста — копирайтер дописал слово, и перенос встал посреди фразы. h1 { text-wrap: balance; } Вместо ручных переносов — одно свойство на заголовок. text-wrap: balance заставляет браузер перебрать точки переноса и выбрать ту раскладку, где строки выходят примерно одной длины. Одинокое слово подтягивается наверх, а разметку трогать не нужно: поменяется текст — браузер пересчитает заново. Рассчитано на короткие блоки: заголовки, подписи к карточкам. Абзац на десять строк браузер балансировать не станет — дорого по отрисовке. Chrome 114+, Firefox 121+, Safari 17.5+; старые браузеры строку проигнорируют. 🔥 — если полезно @glo_academy | #js_day
402
13
Нашей школе сегодня аж 10 лет! Кругленькая дата)) Обычно в этот день у нас стартует большая акция ко дню рождения с разными н
Нашей школе сегодня аж 10 лет! Кругленькая дата)) Обычно в этот день у нас стартует большая акция ко дню рождения с разными новыми программами Но сегодня решили отдохнуть, а все активности перенести уже на завтра Столько всего было за это время, вы не представляете: много людей приходило и уходило — и из команды, и из преподавателей, и студентов уже набралось за 10 тысяч человек В разное время к проекту были причастны разные классные люди, для которых, надеюсь, этот опыт остался приятным теплым воспоминанием Вообще пока собираю этот пост, становится и грустно, и весело, и приятно за этот пройденный путь, хах, хорошо, что это не живая речь)) В общем — с днём рождения этот проект! И спасибо каждому из вас, кто читает посты здесь или в других наших каналах, ходите на интенсивы, изучаете с нами языки и инструменты. Спасибо! ❤️ Завтра стартанем традиционну большую акцию по случаю дня рождения школы — и там представим новые блоки и обновления программ под современные треования Как обычно самыми первыми обо всём узнают подписчики закрытого канала, ну а потом уже выкатим на всех Если вы хотите быть среди первых — переходите по ссылке, через пару часов админ всех запустит) 👉Попасть в сверхъсекретный тг-канал Хорошего вам воскресенья 😍
373
14
بدون متن...
371
15
📐 Лендинг караоке-клуба Сложный макет на русском языке с адаптивом @glo_academy | #макеты
📐 Лендинг караоке-клуба Сложный макет на русском языке с адаптивом @glo_academy | #макеты
380
16
⚡ Один хук заменяет три useState в форме Знакомый набор: состояние под ответ сервера, под ошибку, под «сейчас отправляется» —
⚡ Один хук заменяет три useState в форме Знакомый набор: состояние под ответ сервера, под ошибку, под «сейчас отправляется» — плюс try/catch/finally, где забываешь снять флаг и кнопка остаётся серой навсегда. async function subscribe(prevState, formData) { const email = formData.get('email'); if (!email.includes('@')) return { message: 'Проверь почту' }; await api.subscribe(email); return { message: 'Готово' }; } const [state, formAction, isPending] = useActionState(subscribe, {}); <form action={formAction}> <input name="email" /> <button disabled={isPending}>Подписаться</button> </form> useActionState убирает обвязку. Функции приходит formData, она возвращает новое состояние, а isPending React считает сам — это настоящий статус запроса, не флаг на глазок На всякий случай: если бросишь исключение вместо возврата состояния — React отменит очередь вызовов и уронит ближайший Error Boundary. Лови ошибку внутри действия, возвращай её состоянием 🔥 — если полезно @glo_academy | #js_day
410
17
🧰 anime.js Если GSAP кажется тяжеловатым, а на чистом CSS уже не вывозишь — держи anime.js. Четвёртая версия работает через
🧰 anime.js Если GSAP кажется тяжеловатым, а на чистом CSS уже не вывозишь — держи anime.js. Четвёртая версия работает через ES-модули, из коробки умеет stagger-анимации (когда элементы анимируются по очереди с задержкой), крутит SVG, CSS-свойства и просто JS-объекты. Апи простой: указал что анимировать, задал easing — готово. https://github.com/juliangarnier/anime 🔥 — если было полезно @glo_academy | #инструменты
414
18
👩‍💻👩‍💻 @glo_academy
👩‍💻👩‍💻 @glo_academy
451
19
✂️ Переключатель-тумблер из чекбокса без JS Тумблер собирается из обычного чекбокса, без лишних элементов: сам уезжае
✂️ Переключатель-тумблер из чекбокса без JS Тумблер собирается из обычного чекбокса, без лишних элементов: сам <input> уезжает за экран, а рядом стоит <label>, стилизованный под переключатель. Кружок внутри рисуется через ::after. .switch { position: relative; display: inline-block; width: 46px; height: 24px; background: rgba(0,0,0,.25); border-radius: 22px; transition: .3s; } .switch::after { content: ''; position: absolute; inset: 1px auto auto 1px; width: 22px; height: 22px; border-radius: 50%; background: #fff; transition: .3s; } :checked + .switch { background: #7983ff; } :checked + .switch::after { transform: translateX(22px); } Дальше всё делает селектор :checked — двигает кружок вправо и красит подложку. Состояние хранит сам чекбокс, JS не участвует. Только не прячь его через display: none: элемент выпадет из фокуса, и с тумблером перестанут работать клавиатура и скринридеры. Уводи за экран позиционированием. ❤️ — если понравился пост @glo_academy | #snippets
433
20
🎨 Фокус на кнопке подсвечивает всю карточку Кнопка внутри карточки при табе получает свою рамку фокуса — и она едет вместе с
🎨 Фокус на кнопке подсвечивает всю карточку Кнопка внутри карточки при табе получает свою рамку фокуса — и она едет вместе с кнопкой, если та меняет размер или прыгает по карточке. Выглядит криво. .bento-card:has(button:focus-visible) { outline: 2px solid var(--color-primary); } .bento-card button { outline: none; } Вместо рамки на самой кнопке подсвечиваем родителя через :has. :has() — это селектор наоборот: обычно ты стилизуешь детей по родителю, а тут родитель проверяет, что происходит внутри него. .bento-card:has(button:focus-visible) читается как «карточка, в которой кнопка сейчас в фокусе от клавиатуры» — и рамку рисуем уже на всей карточке, а не на кнопке. :focus-visible, а не :focus — иначе рамка будет появляться и при клике мышкой, а не только при навигации с клавиатуры. Chrome 105+, Firefox 121+, Safari 15.4+. 🔥 — если было полезно @glo_academy | #css_day
427