TGViewer
Channel Public Channel
Glo Academy

Glo Academy

@glo_academy

Бесплатные уроки по HTML/CSS/JavaScript, лайфхаки для верстальщика и бесплатные дизайн-макеты для портфолио.

По рекламе — @yankovsky_ads
Купить рекламу напрямую https://telega.in/c/glo_academy
Subscribers
3.76K
Photos
1.3K
Videos
34
Links
951
Recent Posts 20 shown
Post #2734 145
📐 Лендинг жилого комплекса

Макет средней сложности без адаптива на русском языке

@glo_academy
Post #2733 205
⚡ Одна строка разлогинит все вкладки сайта

Нажал «Выйти», а в соседней вкладке всё ещё открыт кабинет: кнопки живые, данные на месте. Обычно это чинят через localStorage: пишут туда значение, в других вкладках ловят событие storage, парсят строку и удаляют ключ.

const channel = new BroadcastChannel('auth');

// во вкладке, где нажали «Выйти»
channel.postMessage({ type: 'logout' });

// в остальных вкладках сайта
channel.onmessage = (e) => {
if (e.data.type === 'logout') redirect('/login');
};


new BroadcastChannel('auth') открывает канал с именем auth. Вкладка, где нажали «Выйти», отправляет в него объект через postMessage. Остальные вкладки открыли канал с тем же именем и ловят этот объект в onmessage.

Объект уходит как есть, без JSON.stringify, и в хранилище после него ничего не остаётся.

Отправитель своё сообщение не получает, поэтому вкладку с кнопкой уводи на вход отдельно. Работает во всех браузерах, в Safari с версии 15.4.

🔥 — если было полезно

@glo_academy | #js_day
  • 🔥 6
Post #2732 228
🧰 pico

Нужна страница входа или админка для пет-проекта, а возиться со стилями полей и кнопок не хочется. Без CSS браузер вытягивает форму в одну строку шрифтом Times — слева на ролике видно, как это выглядит. Тащить ради пары экранов Bootstrap с классами на каждом теге — перебор.

Pico стилизует сами теги. Подключаешь один файл, пишешь обычные form, label, input и button, и форма выглядит как справа на ролике, хотя классов в разметке нет ни одного. Состояния pico берёт из атрибутов доступности, которые в форме стоит ставить и так: поле с aria-invalid краснеет, чекбокс с role="switch" становится тумблером, кнопка с aria-busy показывает спиннер.

Тёмная тема подхватывается из настроек системы, а data-theme="dark" включает её вручную — на всю страницу или на один блок. Весит pico около 11 КБ в gzip, в комплекте 20 цветовых схем.

https://github.com/picocss/pico

🔥 — если было полезно

@glo_academy | #инструменты
  • 🔥 8
Post #2730 294
✂️ Состояние элемента в атрибуте вместо трёх классов

classList.add('loading'), потом add('error'), где-то забыли снять — и на элементе одновременно висят loading и completed. Какой стиль победит, решает порядок правил в файле. Вместо трёх классов держи состояние в одном data-атрибуте:

<div class="order" data-state="loading">…</div>

order.dataset.state = 'completed';

.order[data-state="loading"] { opacity: 0.5; }
.order[data-state="error"] { border-color: red; }
.order[data-state="completed"] { border-color: green; }


У атрибута всегда одно значение: новое вытесняет старое, двух состояний сразу не бывает. Из JS оно меняется одной строкой через dataset.state, а CSS цепляется за него селектором [data-state="…"].

На гифке: клик по вкладке пишет новое значение в атрибут, и карточка заказа перекрашивается сама.

Селектор сравнивает значение целиком. Если в атрибут попадёт «loading completed», не сработает ни одно правило — поломку видно сразу.

❤️ — если было полезно

@glo_academy | #snippets
  • ❤ 8
Post #2729 293
🎨 Две карточки в гриде не растягиваются на пол-экрана

Сетка на repeat(auto-fit, minmax(240px, 1fr)) отлично выглядит на двенадцати карточках. Но на странице, где карточек две, каждая растягивается на половину экрана, и макет разваливается. Обычно это лечат max-width на карточке или отдельным классом для коротких списков.

.cards {
display: grid;
grid-template-columns:
repeat(auto-fill, minmax(240px, 1fr));
gap: 16px;
}


Разница в одном слове. auto-fit создаёт столько колонок, сколько влезает по ширине, а пустые схлопывает в ноль, и две карточки делят всю ширину между собой. auto-fill пустые колонки оставляет: они невидимы, но место держат, поэтому карточки остаются той же ширины, что и в полной сетке.

Когда карточек всегда больше, чем колонок, разницы нет. Она вылезает на коротких списках: результаты поиска, два товара в категории, одна новость. На ролике слева auto-fit, справа auto-fill.

🔥 — если было полезно

@glo_academy | #css_day
  • 🔥 11
Post #2728 325
📐 Лендинг ювелирного магазина

Макет лендинга средней сложности без адаптива на русском языке

@glo_academy
  • 🔥 3
Post #2727 354
⚡ Таймаут для 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
  • 🔥 11
  • ❤ 2
Post #2726 336
🧰 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 | #инструменты
  • 🔥 11
  • ❤ 1
Post #2725 341
Так или не так, скажите? 😂

@glo_academy
  • 😁 11
  • 👍 1
Post #2724 367
✂️ Длинное название не растягивает карточку

Название товара на три строки — и кнопки «В корзину» в ряду встают на разной высоте. В 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
  • ❤ 12
Post #2723 367
🎨 Колонки едут в противоположные стороны при скролле

Три колонки карточек: при прокрутке крайние уезжают вверх, средняя — вниз. Раньше это делали слушателем 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
  • 🔥 14
Post #2722 424
📐 Лендинг туристической страховки

Макет средней сложности с адаптивом на русском языке

@glo_academy | #макеты
  • ❤ 1
Post #2721 463
⚡ 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
  • 🔥 11
  • ❤ 2
Post #2719 440
🧰 swup

Между страницами обычного сайта белая вспышка: браузер выгружает одну и рисует другую с нуля. Ради плавности проекты переезжают на SPA и получают в нагрузку роутер, состояние и гидратацию.

swup перехватывает клик по ссылке, подгружает следующую страницу и подменяет только контейнер с контентом, а смену анимирует обычным CSS-переходом. Бэкенд любой: PHP, Django, статика из папки. На ролике слева обычный переход, справа он же через swup.

Плагины добавляют прогресс-бар, предзагрузку ссылки под курсором и анимацию отправки форм. Опция native: true переводит анимацию на встроенный в браузер View Transitions API там, где он есть. Версия 4.10 вышла на прошлой неделе.

https://github.com/swup/swup

🔥 — если было полезно

@glo_academy | #инструменты
  • 🔥 7
  • 👏 3
Post #2718 420
Блочная модель на собаках

@glo_academy
  • 😁 11
  • 🔥 2
Post #2717 446
✂️ Поле телефона открывает цифровую клавиатуру

Открываешь форму на телефоне, тапаешь в поле для номера — и вылезает буквенная клавиатура. Человек жмёт «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
  • ❤ 17
  • 🔥 3
Post #2716 447
🎨 Выравниваем текст без <br>

Заголовок в макете смотрелся ровно, а в браузере последнее слово повисло одно на второй строке. Обычно это лечат руками: ставят <br> в нужном месте или склеивают два последних слова через  . Держится до первой правки текста — копирайтер дописал слово, и перенос встал посреди фразы.


h1 {
text-wrap: balance;
}


Вместо ручных переносов — одно свойство на заголовок.

text-wrap: balance заставляет браузер перебрать точки переноса и выбрать ту раскладку, где строки выходят примерно одной длины. Одинокое слово подтягивается наверх, а разметку трогать не нужно: поменяется текст — браузер пересчитает заново.

Рассчитано на короткие блоки: заголовки, подписи к карточкам. Абзац на десять строк браузер балансировать не станет — дорого по отрисовке. Chrome 114+, Firefox 121+, Safari 17.5+; старые браузеры строку проигнорируют.

🔥 — если полезно

@glo_academy | #js_day
  • 🔥 19
Post #2715 421
Нашей школе сегодня аж 10 лет!
Кругленькая дата))


Обычно в этот день у нас стартует большая акция ко дню рождения с разными новыми программами

Но сегодня решили отдохнуть, а все активности перенести уже на завтра

Столько всего было за это время, вы не представляете: много людей приходило и уходило — и из команды, и из преподавателей, и студентов уже набралось за 10 тысяч человек

В разное время к проекту были причастны разные классные люди, для которых, надеюсь, этот опыт остался приятным теплым воспоминанием

Вообще пока собираю этот пост, становится и грустно, и весело, и приятно за этот пройденный путь, хах, хорошо, что это не живая речь))

В общем — с днём рождения этот проект!

И спасибо каждому из вас, кто читает посты здесь или в других наших каналах, ходите на интенсивы, изучаете с нами языки и инструменты. Спасибо! ❤️

Завтра стартанем традиционну большую акцию по случаю дня рождения школы — и там представим новые блоки и обновления программ под современные треования

Как обычно самыми первыми обо всём узнают подписчики закрытого канала, ну а потом уже выкатим на всех

Если вы хотите быть среди первых — переходите по ссылке, через пару часов админ всех запустит)

👉Попасть в сверхъсекретный тг-канал

Хорошего вам воскресенья 😍
  • 🔥 6
  • ❤ 5
  • 👍 1
Older posts →

About this channel

How can I read @glo_academy without a Telegram account?
TGViewer shows the public web preview Telegram publishes for Glo Academy: recent posts, photos, videos and the subscriber count, with no app, login or account.
How many subscribers does Glo Academy have?
Glo Academy (@glo_academy) has 3.76K subscribers on Telegram, refreshed roughly every 30 minutes.
Does Glo Academy know I viewed it here?
No. Public channel previews carry no viewer identity, and TGViewer has no accounts or tracking of what you look up.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →