Telegram Web
#статья дня

7 апреля 2025 года системе контроля версий Git исполнилось 20 лет!

По этому поводу GitHub (а кто же ещё) провели с автором — Линусом Торвальдсом — интервью.

Выдержки:

– Он не хотел писать систему контроля версий — это казалось скучным. Но BitKeeper перестал быть вариантом, и пришлось самому.

– У него не было «плана» или видения. Всё делал на ходу, по мере необходимости. Даже не знал, насколько всё это станет популярным.

– Git задумывался не как «инструмент для всех», а как «инструмент для меня». И, по мнению Линуса, именно в этом причина успеха.

– Его подход: «не делать предсказаний», особенно в open source. Он сам не ожидал, что Git проживёт 20 лет.

– Команду git bisect называет «одной из умных штук», но уклоняется от выбора любимой команды: «это как выбирать любимого ребёнка».

А прочитать целиком рекомендую тут: https://github.blog/open-source/git/git-turns-20-a-qa-with-linus-torvalds/

Кстати, интервью скоро обещают выложить в формате видео!

#git #anniversary
👍135🤬1🤩1🫡1
#фишка дня

Как контролировать прозрачность фоновых изображений?

Первое, что приходит в голову: «Никак».

Точнее, как — никак. Можно сымитировать фоновую картинку через наложение фона на псевдоэлемент или любой другой элемент вообще, и уже его прозрачность и контролировать.

Но может, как-то ещё?

И таки да!


background-image: url(image.jpg);
background-color: rgba(255, 255, 255,0.2);
background-blend-mode: lighten;


или


background-image: url(image.jpg);
background-color: rgba(0, 0, 0,0.2);
background-blend-mode: darken;


...в зависимости от нужного эффекта.

А в случае с несколькими фонами одновременно, background-blend-mode позволяет делать мультиэкспозицию, как на иллюстрации.

Собственно, пример с lighten: https://codepen.io/alinaki/pen/dPyxdPe

P. S. а в Safari можно через функцию cross-fade.

#css #blend
👍134
This media is not supported in your browser
VIEW IN TELEGRAM
#статья дня

Когда-то давно я в качестве демо накладывания ячеек грида друг на друга сделал табло аэропорта: https://www.tgoop.com/htmlshit/2814

Очень схематичное, конечно, но сделать что-то более симпатичное руки не дошли.

Задо дошли у всем известного нам Jhey!

У него получилось трёхмерное табло, которое выглядит и ведёт себя как настоящее. И, более того, он выпустил прекрасную статью со всеми аспектами имплементации!

От построения модели ячейки, с лепестками и осью, до анимации этой модели: https://craftofui.substack.com/p/time-travel-with-javascript

И, более того, анимация выполнена в двух вариантах: GSAP и WAAPI aka Web Animation API, а это значит, можно обойтись без зависимостей вообще.

Горячая рекомендация, в общем.

#css #gsap #waapi
1🤩13👍95
#такое дня

Очень неожиданная информация всплыла в комментариях к одному из предыдущих постов.

Теперь в Chrome дефолтные стили для тегов b и strong не bold, а... bolder!

Пруф: https://github.com/chromium/chromium/commit/0f34660cbc02352d5deabbf135c4b07303979df5

Судя по дате изменения, это как раз улетело в последнюю (135) версию Chromium и Chrome, соответственно.

Казалось бы, какое мелкое изменение, но уже принесло людям проблем :) А главное, посмотрите сколько тестов!

Да-да, тестов там сильно больше, чем в твоём PR, который меняет вообще всё в проекте.

Ладно, а что кроется-то за этим изменением?

А кроется имплементация последних изменений в спеке: https://html.spec.whatwg.org/multipage/rendering.html#phrasing-content-3

Ведь задача strong и b — выделить текст во что бы то ни стало. А если он уже полужирный? То-то и оно.

Или ещё хуже, глядите, на span стоит font-weight: 100: https://codepen.io/alinaki/pen/XJJrEPo

Видите отличия? Я — нет.

Ладно, кроме шуток, объяснение на MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight#meaning_of_relative_weights

Если 700 на родителе — то 800 на strong/b и так далее.

Чудны дела твои, HTML. Упёрлось же кому-то...

Да, кстати, ещё существует lighter :)

P. S. Safari всё ещё использует bold, а Firefox — тоже bolder. Но когда конкретно Firefox внёс это изменение я пока не знаю.

P. P. S. normalize.css тоже всё приводит к bolder.

#html #bolder #bold
10👍4🤬4🫡3
#новость дня

Figma зарегистрировала словосочетание Dev Mode на себя!

Никогда такого не было и вот опять.

Кроме шуток, Figma направила официальное письмо компании Lovable, которые разрабатывают визуальную AI IDE, c требованием прекратить называть их средство просмотра сгенерированного исходного кода Dev Mode.

Всего у Figma 13 зарегистрированных торговых марок, кроме Dev Mode там ещё есть, например, Schema и слоган "Nothing great is made alone". И слово Config!

Подали они заявку летом 2023, а получили одобрение в ноябре 2024.

Словосочетание Dev Mode, хоть и подразумевается во многих приложениях, до этого момента никем не регистрировалсь и, кстати, нигде в общем-то кроме Figma напрямую и не применяется.

Хотя тут с полей сообщают, что Atlassian применяла ещё в 2021.

Но чтоб прямо регистрировать... Каковы ваши мысли по поводу, котаны?

P. S. Надо бы проверить Google DevTools :)

#trademark #devmode
🤬31🤡192👎2
This media is not supported in your browser
VIEW IN TELEGRAM
#статья дня

Итак, перед тобой задача: поставить заглушку, пока грузится основное изображение.

Нет проблем, говоришь ты, и шлёпаешь серый прямоугольник.

И все такие: «Ну чот...»

Наверное, есть же что-то получше?

Да, есть. LQIP-техники вида, собственно, LQIP, SQIP и BlurHash. Вот, писал тут: https://www.tgoop.com/htmlshit/2565

Ну или генерация всенаправленного градиента по фото: https://www.tgoop.com/htmlshit/3517

Но это всё как-то муторно... вот бы что попроще.

И таки есть! Лин Рада — разработчик из Canva — придумал новую технику LQIP, основанную на CSS. Заключается она в кодировании цветных тёмных/светлых участков короткой последовательностью символов.

Ну, типа:


<img src="…" style="--lqip:192900">


И пример того, что получается, можно посмотреть на иллюстрации.

А сама статья шикарный пример умного использования различного рода координат: https://leanrada.com/notes/css-only-lqip/

Изображение бьётся на 6 частей и фон, уровень светлости этих частей задаётся простым кодом. А дальше в дело вступают простые радиальные градиенты и размытие, которые и дают нужный эффект.

Конечно, математики там сильно больше, чем я сейчас описал, потому очень рекомендую хотя бы пролистать её.

Кстати, там же есть и скрипт для обработки картинок, чтобы не гадать координаты самому.

#css #lqip #math
👍188
#инструмент дня

partysocket — это миниатюрная (всего ~2 КБ!) обёртка над WebSocket, которая делает их использование гораздо приятнее.

📦 Что это такое?

По сути, это просто WebSocket-клиент, но с «магией»: автоматические переподключения, буферизация сообщений при обрыве, устойчивость к сбоям — и всё это без лишнего кода.

💬 Как выразился автор:
"A tiny abstraction (like, 2kb) on top of websockets that adds reconnections/buffering/resilience + optional React hooks. Doesn’t even need PartyKit or Cloudflare!"


🚀 Особенности:
- Поддержка в браузере и Node.js
- Нативное API (`onmessage`, send, onopen, и т.д.)
- Работает с любым WebSocket-сервером (не только с PartyKit)
- Встроенные переподключения и буферизация
- Есть React-хуки
- Весит всего около 2 КБ

🛠 Пример:

import { PartySocket } from "partysocket";

const socket = new PartySocket({
host: "example.com",
room: "main-room", // опционально — удобно для namespace'ов
});

socket.addEventListener("message", (evt) => {
console.log("📨", evt.data);
});

socket.send("Hello, world!");


📈 Уже более 100K скачиваний в неделю.

🔗 Подробнее и установка:
https://www.npmjs.com/package/partysocket

Буду пробовать в следующем #проект-е дня.

#websockets
👍306🫡2
This media is not supported in your browser
VIEW IN TELEGRAM
#инструмент дня

Вы только посмотрите на эту красоту!

Да, я в курсе, что компонентов для красивого прокручивания цифр у нас какое-то невероятное количество, но до сих пор не было ничего настолько универсального и простого в использовании.

И не только для React! Vue и Svelte тоже там.

Итак, встречайте: NumberFlow от Максвелла Барвиана.

GitHub: https://github.com/barvian/number-flow
Документация и демо: https://number-flow.barvian.me/

Настраивается формат чисел, параметры анимированных переходов. И, собственно, никаких скрытых зависимостей.

Прекрасное.

#react #number #transition #бородач
31
#нытьё дня

Неожиданно, пост дедовского нытья!

Раньше мы сами выбирали библиотеки. Скачивали архивы, клали их в vendor, подключали в коде. Всё было сложно, но понятно: ты знал, что именно ты ставишь, откуда оно, и зачем.

Потом появились Bower, npm, yarn — и стало проще. Одной командой можно было добавить любую зависимость. Но с этой простотой пришла и новая проблема: стало слишком легко установить что-то не то.

Теперь в игру вступил ИИ. Он подсказывает код, генерирует функции, предлагает решения. Иногда вместе с ними — и зависимости: import x from 'some-lib'. Всё бы ничего, но...

1. LLM генерирует код, который подключает внешние пакеты — это ожидаемо.
2. Иногда эти пакеты вымышленные, они не существуют.
3. Злоумышленники это поняли и публикуют настоящие пакеты с такими "выдуманными" именами.
4. Теперь LLM генерирует код, который подключает вредоносное ПО — и оно успешно устанавливается.

ИИ не различает добро и зло. Он просто делает то, что, по его модели, «похоже на правильное решение». А злоумышленники подстраивают реальность под эту модель.

Когда всё слишком легко, слишком удобно — легко забыть, что ты ставишь, откуда и зачем. И тогда vendor заполняется не тобой, а кем-то другим.

Естественно, это не только о фронтенде. Проблеме в том или ином виде подтверждена любая система пакетов. И даже операционные системы! Кастомные репозитории не вчера придумали.

Понятное дело, что проблему частично можно исправить, добавив в промпты реальные списки пакетов или проведя хоть какой-то анализ сферы. Но это же надо думать :)

Осторожнее, котаны.

#ai #vulnerability
👍345
#инструмент дня

Иногда хочется получать уведомления о завершении скрипта, ошибке на сервере или любом другом событии — без регистрации, API-ключей и костылей.

ntfy.sh — минималистичный и мощный сервис пуш-уведомлений, который идеально справляется с этой задачей.

Отправить уведомление можно одной строкой:


curl -d "Бэкап завершён успешно " ntfy.sh/my-topic


А теперь представь: ты ставишь это в конце крон-джоба или CI-пайплайна, и тебе тут же прилетает пуш на телефон, в браузер или куда угодно.

Особенности:

> Поддержка Web, iOS и Android (через приложения)

> Подписка на топики через браузер или curl

> Можно отправлять заголовки, приоритеты, вложения

> Есть self-hosted режим (на Go, легко разворачивается)

> Поддерживает MQTT и WebSockets

🔐 Безопасность? Можно настроить basic auth и TTL сообщений. Но важно понимать, что в бесплатной версии сервиса топики не резервируются, являясь по факту паролями. Security over obscurity, но что делать.

Если нужно что-то более секьюрное — всегда можно написать себе телеграм-бота, ну.

Пример с заголовком и высоким приоритетом:


curl -H "Title: Внимание!" \
-H "Priority: urgent" \
-d "На сервере заканчивается место!" \
ntfy.sh/my-topic


Открытый исходный код, лёгкий в использовании и отлично документирован.

👉 Официальный сайт: https://ntfy.sh/

#push #notification
👍227👎1🫡1
#фишка дня

Селекторы атрибутов штука довольно удобная если правильно их использовать. Особенно хорошо они раскрываются с aria-атрибутами вроде aria-hidden, aria-pressed и так далее.

Да даже элементарные кнопки соцсетей весьма неплохо выглядят в виде data-social=“twitter”, чтобы не замусоривать пространство классов. Или вообще a[href*=“twitter.com”], если собрались на символах экономить.

В React строить API компонента на data-атрибутах тоже выходит весьма и весьма элегантно.

Вот только есть нюанс: селекторы атрибутов — регистрозависимы. Чтобы сделать их независимыми — стоит добавить модификатор i, то есть:

[data-social=“twitter” i]

Свалидирует

<div data-social=“Twitter”>
<div data-social=“twitter”>
<div data-social=“TWITTER”>

…ну и если хотите ровно наоборот — есть модификатор s. Но оно совсем новое и для частных случаев, которые по-умолчанию и так регистронезависимы (вроде type, checked, disabled).

#attribute #css #case #бородач
👍265
#статья дня

Ох, что тут принесло!

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

Далеко ходить не надо: Google Sheets, Google Docs, Miro, да даже Microsoft в онлайн и не очень офисных пакетах это позволяет. И, кстати, онлайн игры это тоже самое что ни на есть приложение для совместной работы. Особенно это интересно в файтингах, но об этом потом.

Общее название структур данных для организации подобного это CRDT. Conflict-free Replicated Data Type, или, по-русски, бесконфликтная репликация данных.

Там на самом деле довольно сложная алгебра, можно хотя бы глянуть программу обучения CRDT: полностью доступные распределенные системы, чтобы сойти с ума. Но гораздо интереснее посмотреть на примерах, как это работает. И сегодняшняя статья дня это позволяет.

Встречайте: https://jakelazaroff.com/words/an-interactive-intro-to-crdts/

Статью не назвать простой, а реализацию — промышленной, но оно работает и очень впечатляет! Всем рекомендую, котаны.

#crdt #algorithm #бородач
10👍6
Forwarded from Alex Chuev
У Фигмы была интересная статья про то, как они это делали и почему они отошли о чистого CRDT

https://www.figma.com/blog/how-figmas-multiplayer-technology-works/
👍64
#баг дня

Преамбула

Некий сервис, назовём его Doodle Lampolytics, заставил всех своих клиентов переползти с модели подсчёта просмотров страниц на модель подсчёта событий.

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

И если раньше мы в нагрузку к «просмотру» передавали так называемые индивидуальные размерности и метрики, привязанные к сессии, то теперь — каждое событие может нести индивидуальный их набор.

Не в последнюю очередь это связано с ужесточением запретов на слежку за посетителями сайтов.

Поскольку в типичном проекте зачастую присутствует не одна сотня событий/страниц, то переезд сопровождается знатным перетряхиванием всей аналитики.

Суть

Суд да дело, приходим мы к идее передачи события с неким контекстом:

trackEvent('event_name', context) {}

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

Передаём туда, например, productId и orderId — и получаем трекинг истории конкретного продукта или заказа. Удобно, когда продукт сильно кастомизированный. Можно накинуть туда optionId и следить, какие продукты какими опциями нашпиговывают.

Таким образом, мы отсылаем объекты вида:

productId,
optionId,
orderId,
locale,
}


Потом объект из camelCase конвертируется в snake_case, как того требует документация, и дёргается некий API. Запомните этот момент.

И всё, поехали в продакшен. События уходят, счастье. Заодно, те же самые события, за некоторым исключением, можно пихать в сервисы вроде Sentry.

И всё бы ничего, но интерфейс Doodle Lampolytics настолько проклят, что оказалось намного проще выгружать данные оттуда сразу в Doodle LargeQuery и SQL-ем их запрашивать.

Но в какой-то момент времени мне это радикально надоело. Мне нравилась простота старого интерфейса, и я решил разобраться в новом. Проблема была в том, что я там не мог найти не только половину событий, но и их параметры.

Я почитал документацию, нашёл где создавать свои размерности и метрики на основе передаваемых параметров — в админке — захожу туда и наблюдаю следующую картину:

product_ıd,
option_id,
option_ıd

— Какого хера?! — заорал я, я же был в офисе.

Но параметры с ı вместо i исчислялись десятками, в то время как остальные — десятками тысяч. И я зачем-то успокоился. Подумал, что это косяк ламполитики, с которым можно разобраться попозже.

Но сегодня я зашёл в наш прекрасный чат, зачем-то ткнул в аватарку одного из подписчиков и увидел у него в истории некую песню с названием Bakı.

И тут до меня резко дошло, какой я идиот.

Прежде чем читать дальше, вы можете посмотреть на код функции, которой мы преобразуем camelCase в snake_case: https://github.com/jonschlinkert/snakecase/blob/master/index.js

Особо внимательные, наверное, уже догадались, в чём проблема. А ведь мы даже тесты написали.

Поскольку не все пройдут по ссылке, я приведу кусочек:

const lowercase = (input = '', options) => input.toLocaleLowerCase(options?.locale);


Ничего не смущает? Я подожду.

...

Да, правильно. Если забыть передать локаль (язык клиента, сервера в нашем случае), то будет взята переменная среды.

И для кого-то из наших клиентов в этой переменной оказался турецкий (или узбекский) язык.

В которых нет буквы i, вместо неё — ı.

Вы все правильно поняли, мы не полностью контролируем среду выполнения. Это так называемый Doodle AppsScript. Он исполняется на языке, в котором открыт офисный инструмент посетителя.

Естественно, мы локаль передать забыли. Хороший вопрос, почему мы вообще не проверили это поведение изначально... но тут как есть.

Стыдно? Стыдно. Зря я винил Doodle Lampolytics.

#бородач
20👍7🫡6
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня

Итак, сегодня я спросоня долго смотрел на этот пример от Джея и никак не мог понять, какого фига тут происходит.

Не, ну я вижу, что в итоге получается градиентная граница, но... но почему?

И тут до меня дошло: оказывается, при настройке фона можно фактически указывать боксовую модель! Ну то есть называется-то оно background-origin, но по факту работает по тем же принципам, что и box-sizing.

Итак, три значения: border-box, padding-box и content-box.

Выходит, border-box заполнит фон, включая границы, padding-box — до полей, a content-box — по контенту.

Ну и для градиентных границ (к сожалению, только с непрозрачным фоном), получается так:

article {
background: // layer them up with different origin!
linear-gradient(var(--bg), var(--bg)) padding-box,
var(--gradient) border-box;
border: 4px solid transparent;
}

Обратите внимание, котаны, такое прокатывает только с фоном-изображением или градиентом, для сплошного заполнения просто указать цвет не выйдет!

Ну и пример, конечно же: https://codepen.io/alinaki/pen/QWYoPpx

#css #background #origin #бородач
👍186
Forwarded from SelenIT
Небольшое уточнение: за границы распространения фона отвечает не background-origin, а background-clip, просто в шортхенде значение брксовой модели устанавливает сразу их оба (абзац после первого Note в https://drafts.csswg.org/css-backgrounds/#background) 😳

Скоро можно будет и с прозрачными фонами — через background-clip: border-area (пока только в Сафари). Зато с недавних пор как минимум в Хроме можно задавать сплошной цвет градиентом без повторения и лишних цифр, просто *-gradient(red) и т.п.
👍84
#фишка дня

Когда-то давно я слышал о таком свойстве, как text-align-last.

Что оно делает? Ну, думаю, всё понятно из иллюстрации :)

Работает с последней строкой индивидуально, позволяя сделать более приятные глазу переходы текста, соответствующие остальной стилистике. Вот хорошая статья на тему: https://www.stefanjudis.com/today-i-learned/how-to-align-the-text-of-the-last-paragraph-line/

С интерактивным примером, как вы любите.

Почему я акцентировал на нём внимание?

Да просто я знал о нём ещё тогда, когда оно толком нигде не поддерживалось. Вот в IE работало, буквально, а в Chrome нет. И как-то все на него забили в итоге.

В этом есть небольшая беда так нами любимых «the future CSS tip». Наиграешься, разочаруешься, и забудешь :(

Но есть же наш уютный канальчик, мы тут всё вспомним :)

#css #thefuturepast #бородач
👍129
#шпаргалка дня

Уникальное предложение!

Берёте короче эту пирамиду код-ревью и ваши пулл-реквесты станут не только вкусными, но и полезными: https://www.morling.dev/images/code_review_pyramid.svg

Такая себе пирамида Маслоу, но для обсуждения качества кода. От базовых вещей (но не опускаясь до того, что можно сделать автоматически) до того, что сделает ваш код действительно красивым.

#pr #process #work #бородач
👍11🤩32🫡2
#статья дня от подписчика

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

Спойлер: вы у меня все любимые, котаны.

Впрочем, слово автору!

🔥 Slow SPAs Kill Conversions — и я знаю, как это исправить.

Привет! Я Олег, занимаюсь фронтендом и люблю разбираться, как сделать веб быстрее, легче и умнее. Когда SPA начинает тормозить, страдает не только UX, но и бизнес - падает конверсия, растёт отток

В своей новой статье «Улучшаем производительность SPA» я разложил по полочкам:
— Где именно тормозит ваше приложение (спойлер: не только в бандле)
— Как грамотно внедрить ленивую загрузку и код-сплитинг
— Зачем вам Web Workers и виртуализация, если хочется отзывчивости даже на слабых устройствах

p.s спасибо всем, кто даёт фидбэк, шарит и просто читает - вы крутые

Читай гайд по оптимизации
https://dev.to/oltrenin/improving-spa-performance-2k2g
👍11🤩7👎32🤡1🫡1
#такое дня

Если этим утром вы проснулись с диким синдромом самозванца и считаете, что уж вас-то точно переоценили, помните.

Где-то в Google есть фронтенд-разработчик, PM и QA, которые не осилили скелетоны и скроллбары. И получают они сильно больше денег чем вы, котаны.

Синдром самозванца, вроде, стал полегче, но в целом стало гораздо хуже, не правда ли? :)
👍27🫡63
2025/10/21 13:20:58
Back to Top
HTML Embed Code: