Будни разработчика
14.7K subscribers
1.18K photos
334 videos
7 files
2.01K links
Блог Lead JS-разработчика из Хельсинки
Автор: @bekharsky

По рекламе: https://telega.in/channels/htmlshit/card?r=GLOiHluU или https://t.me/it_adv

Чат: https://t.me/htmlshitchat

№5001017849, https://www.gosuslugi.ru/snet/679b74f8dad2d930d2eaa978
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня

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

Например, как затемнить все элементы, кроме того, на который наведена мышь?

Вот как-то так:
main:has(article:hover) article:not(:hover) {
opacity: 0.3;
}


Собственно: https://codepen.io/alinaki/pen/XWGdadP

Впрочем, похожий, хоть и не настолько гибкий, эффект достигается и без :has:
main:hover article:not(:hover) {
opacity: 0.3;
}

Пруф: https://codepen.io/alinaki/pen/OJqNjWb

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

Но тут кому как, конечно.

#css #trick #hover
13👍10
This media is not supported in your browser
VIEW IN TELEGRAM
#заметка дня

Элемент marquee, который когда-то давно долгое время использовался для создания бесконечной бегущей строки, давно объявлен устаревшим. При этом, желание создавать бегущие строки у дизайнеров и заказчиков никуда не исчезло.

Давайте сразу определимся: хоть он и устаревший, он всё ещё прекрасно работает... в Chrome. Кому-то из разработчиков было весьма интересно переделать его на Shadow DOM и оптимизировать. В Safari и Firefox всё довольно плохо, тормозит безбожно. Поэтому, если ваша задача сделать киоск или использовать в приложении на Electron — не мучайте себя, берите его.

Поэтому долгое время бегущие сроки создавали, используя translate на контейнер и дублирование содержимого. Например, так: https://codepen.io/studiojvla/pen/qVbQqW

Но мы же с вами ровные, зачем нам такие технологии? Можно же жить в 2024 году и не дублировать контент почём зря!

А сделать это можно просто: через CSS-переменные и анимацию индивидуальных элементов! Для этого прямо в разметке указываем порядковый номер элемента и передаём его в определение анимации: https://codepen.io/thebabydino/pen/BaMqgPO?editors=1100

Пример выше — от Аны Тюдор. Вот то же самое, но без Pug, чтобы легче было понять принцип: https://codepen.io/alinaki/pen/poYyaMJ?editors=1100

В чём плюс такого подхода?

1. Никакого дублирования
2. Короткий код
3. Можно применить любые трансформации к каждому элементу, помимо сдвига
4. Фон принадлежит контейнеру и никуда не сдвигается. Можно прозрачность наложить, можно маски, можно глассморфизм... далее — везде.

Не нужны даже псевдоэлементы чтобы затухание сделать (собственно, маска).

Крутота же, котаны? Крутота.

#marquee
👍243
#ссылка дня

Сложно давать ссылки на что-то поддерживаемое какой-нибудь компанией и не быть обвиненным в рекламе.

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

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

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

На помощь приходят подборки тестовых! Вот, например, от Хекслета: https://github.com/Hexlet/ru-test-assignments

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

Полезная штука, котаны. И не только для начинающих!

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

#work #assignment #list #бородач
👍20🤡1
#фишка дня

Как использовать CSS-переменную в псевдоэлементе?

Просто так в content запихать её нельзя. Т. е.
.cell::before {
content: var(--i);
}

...работать не будет.

К счастью, в CSS есть весёлая штука, счётчики: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_counter_styles/Using_CSS_counters

А вот они уже содержать переменную очень даже могут:
.cell::before {
counter-reset: i var(--i);
content: counter(i);
}


А вот зачем мне это понадобилось — расскажу завтра. Спойлер: sneak peek есть в чате (@htmlshitchat) и наверняка вы это видели незадолго до того, как попали на канал 😉

Оставайтесь на связи, котаны! Завтра будет.

#css #counter #var
Please open Telegram to view this post
VIEW IN TELEGRAM
6
This media is not supported in your browser
VIEW IN TELEGRAM
#заметка дня

Многим из вас знакомо видео выше. неудивительно, ведь я использую его как промо канала. Не всегда удачно, но почти 12000 вас уже здесь :)

Так вот, на иллюстрации — не совсем оно. А имитация на HTML и CSS. Оригинальное было сделано моим коллегой в After Effects.

Но на чистом CSS подобные прыгающие анимации сделать было невозможно... до недавнего времени. Теперь же на Chrome или Firefox (не iOS), есть возможность использовать функцию анимации linear(). Обратите внимание, не linear!

Вот так:
linear(0, 0.14 4.43%, 0.93 16.722%, 1.14 24.312%, 1.15 29.933%, 1.01 43.094%, 0.97 50.995%, 1 76.878%, 0.99);


Это буквально параметры кривой: https://developer.mozilla.org/en-US/blog/custom-easing-in-css-with-linear/

Раньше у нас в лучшем случае была возможность описывать кривые Безье, но добиться правильного пружиняшего эффекта с ними было невозможно :)

Теперь о задержки проигрывания на диагоналях...

Сначала я упёрся в аналитическое решение через nth-child: https://codepen.io/alinaki/pen/PoLNMgj

И всё прекрасно получалось, но из-за повторяющейся природы nth-child, чтобы выйти за пределы главной диагонали пришлось внести ограничения по номерам элементов, иначе, начиная с 9 диагонали, затрагивалась 2 (из 12):
.cell:nth-child(7n + 10):not(:nth-child(-n + 17)) {
--i: 10;
}

...делать мне этого очень не хотелось.

Собственно, запись :nth-child(-n + 17) буквально выделяет первые 17 нод.

И тут я обратил внимание, что суммы индексов колонки и строки на элементах по нужным мне диагоналям одинаковы, так что с помощью Pug я их передал в CSS-переменные: https://codepen.io/alinaki/pen/mdoEPbR

Как-то так:
each r, rx in rows
each c, cx in cols
- d = rx + cx + 1
.cell(style=`--dia: ${d};`)


А почему я упомянул вчера счётчики? Ну куда-то выводить переменную диагонали для отладки надо было же.

В обоих примерах есть ещё одна маленькая фишка, позже выкачу её и объяснение.

Всем неглавных диагоналей за мой счёт, котаны!

#css #matrix #pug
👍131
#фишка дня

В посте про поиск диагоналей в сетке и CSS-функции linear() вы могли заметить, что анимацию можно перезапустить, кликнув по экрану. Вот, кто пропустил: https://t.me/htmlshit/2439

И, на самом деле, сходу можно придумать, как этого достичь: удалить элемент и добавить его снова.

Но это звучит как какой-то бред. Если анимация добавляется по классу, разве нельзя просто взять и этот самый класс передёрнуть?

К сожалению, нет. Браузеры — штуки ленивые. Точнее, они берегут вычислительные ресурсы, батарею... и не знаю, что там ещё.

Убрали класс, вернули класс... дерево не поменялось. Браузеру, стало быть, пофигу и никакого reflow (перестройки лейаута), так необходимого для анимации, не случится.

А чтобы случилось, нужно просто подёргать за разные ниточки. Например, обратиться к element.offsetWidth или element.offsetHeight.

Эти свойства — ленивые, они вернут ширину или высоту элемента с учётом отступов, полей, скроллбаров...

Чтобы их взять точно и в нужный момент, браузеру придётся остановить выполнение JS, выполнить обновление "экрана" и, собственно, вычислить.

Кстати, если этот путь кажется слишком хитрожопым, можно воспользоваться Web Animations API, достать анимации документа и перезапустить:

const replayAnimations = () => {
document.getAnimations().forEach((ani) => {
ani.cancel();
ani.play();
});
};


Подробнее: https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API

Под капотом произойдёт всё тот же самый reflow, но магии станет сильно поменьше.

#css #animation
👍6🤬1
#такое дня

Нераскрытая история веба. Этим невозможно не поделиться:

1990: HTML invented
1994: CSS invented to fix HTML
1995: JS invented to fix HTML/CSS
2006: jQuery invented to fix JS
2010: AngularJS invented to fix jQuery
2013: React invented to fix AngularJS
2014: Vue invented to fix React & Angular
2016: Angular 2 invented to fix AngularJS & React
2019: Svelte 3 invented to fix React, Angular, Vue
2019: React hooks invented to fix React
2020: Vue 3 invented to fix React hooks
2020: Solid invented to fix React, Angular, Svelte, Vue
2020: HTMX 1.0 invented to fix React, Angular, Svelte, Vue, Solid
2021: React suspense invented to fix React, again
2023: Svelte Runes invented to fix Svelte
2024: jQuery still used on 75% of websites
👍22🤩32
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня

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

И это API document.getAnimations(), позволяющий не только получить список всех CSS-анимаций, но и, внимание, выставить промис и дождаться их выполнения! 🤯

const animations = document.getAnimations()
.map(a => a.finished)
await Promise.all(animations)


Сразу кодпен: https://codepen.io/alinaki/pen/rNoEOwX

*с некоторых пор я начал форкать пены, потому что пропадают иной раз

Теперь о применимости.

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

Ну а разработчикам промо-сайтов важность синхронизации действий и анимаций объяснять не надо.

Отличный пример забытых технологий 🙂

Не, ну серьёзно, оно с 75 Firefox доступно, как я мог его проглядеть?

А я знаю, как. Я же писал уже, что PR-служба Chrome работает прекрасно только в том случае, когда что-то появилось там первым...

#css #js #animations #promise #бородач
👍141
This media is not supported in your browser
VIEW IN TELEGRAM
#статья дня

А знаете ли вы, котаны, что такое безопасный треугольник печали? Aka safe triangle.

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

Да-да, в вашей Windows или MacOS такое тоже есть. Проверьте сами.

Собственно, почему я о нём заговорил? А тут вышла новая статья Ахмада Шадида и посвящена она такой важной вещи как "область взаимодействия".

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

В общем, с чего всё началось, зачем это нужно и как сделать сайты удобными — в первой интерактивной статье Шадида: https://ishadeed.com/article/target-size

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

#css #ui #ux #safe #target
👍4210🤩2
#новость дня

14 января 2006 года на конференции BarCamp в Нью-Йорке Джон Ресиг представил первую версию jQuery.

Что это значит?

Что jQuery сегодня исполнилось 18 лет!

Сейчас, пожалуй, невозможно представить как же было сложно писать веб без jQuery.

Скольким подписчикам канала меньше? У вас всё ещё впереди, котаны :)

Да и у остальных тоже, камон.
👍213🤡1
#заметка дня

Итак, котаны, у нас сегодня офигительная информация от Глеба. Вы уже с ним знакомы, он автор библиотеки extended-fetch, расширяющей возможности стандартного fetch. Горячо рекомендую, кстати.

Слово автору.

Наверняка вы сталкивались с проблемой медленного eslint и очень хотели использовать все ядра процессора

По этой проблеме существует issue в репозитории eslint аж с 2015 года, однако лишь в ноябре 2023 года появился PR с добавлением параллелизма при помощи флага --parallel (к сожалению, он до сих пор не смержен).

В комментарии к issue автор PR описывает как его вдохновил пакет @mixer/parallel-prettier: создается очередь и распределяется по процессам с воркерами, а затем их результаты выполнения аккумулируются и создается общий отчет.

По его замерам на 6 ядрах время выполнения eslint снизилось с 4 до 1 минуты исключая правила Typescript, а с ними с 4 до 2 минут.

Конечно же, предстоит решить вопрос с кеширвоанием и шарингом кеша между процессами, ну и никуда не исчезнут нюансы парсинга Typescript.

И совсем недавно появился форк eslint с поддержкой параллельной проверки нескольких файлов.

Всё это очень краткий пересказ, поэтому лучше почитать последние комментари в issue и убедиться, что всё не так плохо и прогресс в сторону улучшения производительности есть.

Всем ускорения, котаны!

#eslint #multicore #parallel
👍6
This media is not supported in your browser
VIEW IN TELEGRAM
#codepen дня

Яркий пример работы UI/UX сообществ.

1. Один популярный в iOS UX-сообществе автор, Робера Гелера, выдвигает идею. Например, индикатор pull-to-refresh совсем необязательно делать чем-то вроде спиннера или капли, как сейчас везде. Ну, типа, зачем это делать, когда есть скроллбар? Ну и делает пример на SwiftUI. Именно его я прикладываю к посту.

2. Потом приходит второй, популярный уже во frontend-кругах (ну Джей, конечно, кто же ещё), и говорит, что это можно легко сделать на CSS и JS.

3. Пока Джей телится с кодпеном, выходит Альваро Монторо и достаёт из широких штанин свой: https://codepen.io/alvaromontoro/pen/JjzEKWG

4. Спустя несколько часов Джей, наконец, прикладывает свой вариант: https://codepen.io/jh3y/pen/gOEgxbd

Грубо говоря, там, конечно, не настоящие скроллбары, а их имитация на SVG, анимированная через GSAP и ScrollTrigger.

Но! В скором времени нас ждёт Scroll-Driven Animations API и можно будет сделать всё то же самое. С нетерпением ждём.

Бросайте вызов устоявшимся практикам, котаны!

#css #ui #gsap #svg
👍265🤩3
This media is not supported in your browser
VIEW IN TELEGRAM
#баг дня

Кастомные скроллбары — штука прекрасная, хоть за 20 лет так и не нашедшая свой путь в стандарты. До сих пор полноценная стилизация возможна только в Blink aka Chromium и WebKit aka Safari.

В Firefox как не работало, так и не работает.

К слову, хорошая статья Ахмада Шадида на тему: https://ishadeed.com/article/custom-scrollbars-css/

Короче, суть бага: если вы решились таки стилизовать скроллбар, то не рассчитывайте, что Safari правильно применит стили по наведению мыши :)

Я, правда, не знаю, кому может прийти в голову менять стили скроллбара по h
over.

Раз сработает, два сработает, а на третий — всё, нет. Смотрим видео, собственно.

Решение
от Брамуса Ван-Дамма довольно забавное: нужно стриггерить инвалидацию стилей, для чего можно рандомной CSS-переменной присвоить неопределённое значение. Вот так:

.section:hover {
--force-rerender: ;
}


Странные вайбы такие... IE-шные.

Короче, как будет ссылка на официальный багтрекер — закину.

Upd. Ссылка на багтрекер: https://bugs.webkit.org/show_bug.cgi?id=267575

#css #scrollbar #safari #bug
👍82
#статья дня

Скорее даже заметка от Софии Валитовой о порядке применения трансформаций в CSS, но концентрация знаний зашкаливает. В чём же весь вопрос?

Как вы можете помнить, не так давно все современные движки браузеров стали поддерживать определение трансформаций не только в правиле transform, но и в индивидуальных. То есть:

transform: translateX(20px) rotate(40deg) scale(1.5);

может быть записано как:

translate: 20px;
rotate: 40deg;
scale: 1.5;


Но так ли это на самом деле? И да и нет. В первом случае порядок важен, во втором — нет, он всегда будет translate👉rotate👉scale. И, естественно, повторяющиеся правила будут схлопнуты.

Подробнее — в заметке Софии. Вообще у неё очень много полезного выходит, глубоко копает в спеки.

#css #transform #бородач
👍13
#такое дня

А давайте, а давайте я вам расскажу про две драмы, произошедшие во фронтенд-сообществе на днях!

Сначала у Дэна Абрамова бомбануло от того, что люди не понимают, что такое RSC aka React Server Components.

Цитата: "React Server Components does not require a server (and never has). i get that this is confusing but i’m at loss what to do. people keep repeating that it does and speak about it as if it were a true fact. can someone spread the word pls?"

Суть в том, что слово Server в RSC не означает необходимость наличия сервера. Нейминг от бога просто.

Там шикарные треды, кстати, затрагивающие историю React вплоть до нечто под названием XHP, подрались по HTMX и сигналам. Короче, вообще не скучно.

Кончилось тем, что Даня Наше Всё пообещал статьи по RSC. Ждём.

Ну а вторая драма чуть менее весёлая.

Есть такой фронтенд-ютубер — Theo Rants. И вот он выкатил видео по поводу вынесенной в иллюстрации штучки: https://youtu.be/cH8VbLM1958

Казалось бы, ну тут-то где драма? А всё просто. В качестве доказательств он привёл обзор проекта уже знакомого нам (даже лично) Ахмада Шадида — https://defensivecss.dev/

Но не упомянул его имя, вообще. Когда ему указали на это — он забанил указавшего :)

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

Ахмад немного раздул скандал и теперь всё в порядке. Но осадок остался.

Я догадываюсь о причине произошедшего, но, пожалуй, воздержусь от озвучивания.

Не будьте токсичными, котаны :)
👍121
#тип дня

Попробую вместо тега #фишка внести что-то новое для TypeScript. Пусть будет "тип", а там посмотрим.

И сегодня на повестке дня запрет определённых ключей при передаче объекта. Например, контекста в трекинге или тех же пропсов в React.

Как правило, контекст в трекинге передаётся в функцию-хелпер, а после — дополняется какими-то переменными среды. Как-то так:


function logEvent(severity: LogSeverity = "info", context: LogContext = {}) {
log(severity, {
type: "event",
userId: "rick@ro.ll",
env: "dev",
...context,
})
}


Понятное дело, нам совсем неохота, чтобы кто-то случайно передал в контекст type, userId или env и затёр всё нафиг.

"Погоди, так разверни контекст повыше", — скажет кто-то умный.


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

Проще сразу не дать сделать странное, как минимум на этапе введения контекста. Наш вариант в итоге стал таким:

type LogContextDefaults = "type" | "userId" | "env";

type LogContext = {
[key: string]: string;
} & {
[key in LogContextDefaults]?: never;
}


Ну и конечно, ссылка на песочницу: пуньк.

Есть предложения получше, котаны? Ну кроме проверки в рантайме :)

#typescript #ts #type
15👍1🤩1
#статья дня

Давно не было интерактивных статей от кого-то, кроме Шадида и Комо :)

Время исправлять.

Сегодня — статья про концепцию и варианты реализации Drag&Drop-интерфейсов от Амита Пателя и Red Blob Games: https://www.redblobgames.com/making-of/draggable/

Давайте сразу: Red Blob Games это не компания, это сайт, собственно, Амита, где он объясняет используемые в играх и интерфейсах концепции: от поиска пути и генерации шестиугольной карты, до простейшего ИИ для игр.

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

Прекрасная статья и проект вообще, моя горячая рекомендация.

#javascript #games #drag #drop
👍22
#фишка дня

Мне снилось, что есть такой сайт, где описаны все виды центрирования контента в CSS...

Я проснулся — а его нет. Зато есть вот что: https://codepen.io/alinaki/pen/VwqXKOL

Здесь собраны шесть вариантов центрирования контента на флексах и гридах и наглядно показана разница между place-content и place-items в разных контекстах! Я, честно, эти правила толком и не использовал... стыд и позор 🤦‍♀️

В общем, не зря утро прошло.

#css #grid #flex #center #бородач
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
#фишка дня

Вроде как все в курсе, что в CSS есть функция filter(). С её помощью мы делаем размытие, дёргаем яркость... тень, опять же!

Но она умеет больше, намного больше. Точнее, умеют фильтры SVG, а функция — на них ссылаться:
filter: url("filters.svg#filterId");

Например, используя фильтр рассеянного света — feDiffuseLighting — можно превратить круг в шар: https://codepen.io/alinaki/pen/OJqmdEJ

А можно сымитировать бумагу, как в примере от Сары Суйедан: https://codepen.io/SaraSoueidan/pen/oppeJM/adc57533be256b5148d5924a5dbd46a3

Или угареть и применить карту смещений: https://www.smashingmagazine.com/2021/09/deep-dive-wonderful-world-svg-displacement-filtering/

SVG-фильтры в принципе позволяют добиться эффекта, похожего на карту нормалей в 3D-графике, но без, собственно, применения WebGL. Иногда этого достаточно.

Спека по ним великолепная просто: https://www.w3.org/TR/2002/CR-SVG11-20020430/filters.html

Хотя, если честно, тяжеловаты они, GPU c WebGL справляется получше. Да и поддержка на iOS так себе.

#css #filter #svg
👍1110
#фишка дня от Гарри Робертса aka csswizardry.com

Когда-то очень давно поднялся вопрос красивого обтекания картинок. И появилась такая вещь: shape-outside.

Естественно, IE эту штуку не поддерживал вообще никогда, да и в целом современное направление фронтенда больше идёт в сторону приложений и блочной структуры, нежели документов с иллюстрациями.

Тем не менее, иногда надо. И поэтому, спешу напомнить: shape-outside нынче очень хорошо поддерживается и если вам нужно оформлять тексты, книги и статьи — самое время!

Если коротко, shape-outside позволяет описать контуры объекта, чтобы текст обтекал его именно по этим контурам. Более того, браузерам не нужен контур, они могут определить его самостоятельно по прозрачным областям PNG!

Вот только в Firefox требуется насильный репейнт... будем думать, как победить. А Safari чуть иначе определяет форму по альфа-каналу, нежели Chrome.

Upd. Важное дополнение! Чтобы правило shape-outside работало адекватно, не прячьте изображения в блоки; Firefox сходит с ума.

Ну и кодпен, конечно же: https://codepen.io/alinaki/pen/WNLVGae

Важный момент, это правило shape-margin, без него текст начинает прилипать к объекту.

Ну а статья, откуда взята фишка, вот: https://csswizardry.com/2023/07/the-http1liness-of-http2/

Весьма интересный обзор проблем протокола HTTP/2, если что.

#css #shape #img #бородач
👍61