Будни разработчика
14.7K subscribers
1.17K 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
#фишка дня

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

Буквально — используя параметры строки запроса (query string parameters).

Ну то есть что-то вроде https://buy.that?title=Product&action=buy&config=2&amount=3, классические GET-параметры, но управляемые с фронта.

А вот как позволить клиенту обновить страницу, сохранив эти параметры? Желательно, без лишней работы и без использования JS вообще.

А очень просто!

<a href="">Reload</a>

Да, вот так просто! Самое классное, что абсолютно валидно и есть в спеках: https://stackoverflow.com/questions/5637969/is-an-empty-href-valid/43340108#43340108

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

Не пишите лишнего, котаны!

#http #html #trick
👍492
#фишка дня

Есть псевдокласс :disabled, который выберет отключенные поля. Есть псевдокласс :read-only, который выберет недоступные для ввода поля (только для чтения).

Вот только есть нюанс.

Отключенные поля они так-то тоже для ввода недоступны. Как же тогда быть?

Использовать селектор атрибута: [readonly].

Пример: https://codepen.io/elad2412/pen/wvpmjGR

Отличие disabled-полей от readonly: первые не отправятся с формой вообще, а значение вторых просто нельзя изменить.

Скелетон вернётся с новыми подробностями о фронтенде завтра.

#css #html #input #бородач
👍19👎3
#фишка дня

Как предотвратить взаимодействие пользователя с элементом?

pointer-events: none — скажете вы.

Да. Но нет. А что насчёт клавиатурного фокуса? А скринридеры? Так не пойдёт.

Благо, есть решение!

Начиная с Firefox 112 и Safari 15.5 у нас наконец-то есть поддержка атрибута inert. Что это такое?

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

То есть, если вы зададите элементу атрибут inert, то:
1. Будет предотвращена обработка события click.
2. Элемент перестанет получать фокус и...
3. ...станет недоступен для скринридеров (исключён из a11y tree).

Поддержка уже давно есть в Chrome, начиная со 102 версии, и теперь, с вводом в строй Firefox 112 — есть во всех современных движках.

Ну и, естественно, присущие атрибуту свойства можно повторить ручками, вот пример: https://codepen.io/alinaki/pen/ZEqJepB

#inert #attribute #html #a11y #бородач
👍292
This media is not supported in your browser
VIEW IN TELEGRAM
#фишка дня

А давайте немного заглянем в будущее.

Наверняка же кто-то из вас делал различные выпадающие списки на замену убогому select. То, почему select такой убогий — это тема для отдельной большой статьи, я ещё пытаюсь собрать материалы. Там не только про него, впрочем... Но не суть.

Так вот, если у вас есть Chrome Canary aka 120, можно пройти в chrome://flags, включить Experimental Web Features и увидеть возможности будущего элемента selectlist.

Уна Кравец собирает различные примеры использования в своей коллекции на Codepen: https://codepen.io/collection/QWeLGB?cursor=eyJwYWdlIjoyfQ==

Вот, например, меню из Airbnb с видеоиллюстрации: https://codepen.io/una/pen/PoXbgVW

А вот GitHub: https://codepen.io/una/pen/KKbNYbo

Там много разных. Повторю: только на Canary и только с Experimental Web Features.

Впрочем, естественно, давно имеется веб-компонент, ведущий себя ровно так же: https://github.com/luwes/selectlist-polyfill

Так что пробовать можно уже сейчас. Пора начинать!

P. S. я тут сделал sortable multiselect combobox на React Downshift. Надо кому инструкцию?

#select #html #future
👍12
#детектив дня

Сегодня в чат пришёл подписчик с забавной проблемой.

Дано: форма с двумя полями, одно просто как HTML-тег, второе — React-компонент. Ну, очевидно, компонент тоже содержит поле ввода.

При нажатию на клавишу Ввод событие onSubmit не происходит, форма не отправляется. Хотя, вроде как, всем известно, что это — стандартное поведение.

Было замечено, что при удалении React-компонента всё отлично работает. И первым предположением стало, что React что-то испортил, или песочница кривая.

Кто-то догадался сделать ванильный пример, поведение сохранилось.

То есть, вот такое:
<form onSubmit="alert('aha')">
<input type="text"/>
<input type="text"/>
</form>

...просто-напросто не работает. Стали копать.

И докопались до спецификации 1995 года для HTML 2.0!

Вот она: https://www.w3.org/MarkUp/html-spec/html-spec_8.html#SEC8.2

И там написано следующее:
When the user indicates that the form should be submitted (using a submit button or image input), the form data set is processed according to its method, action URI and enctype.

Перевожу: чёрным по белому сказано, что форма должна отправляться по кнопке submit (или специальной картинке, но то такое).

То есть, наше предположение о том, что форма всегда должна отправляться по нажатию Ввода — уже неверное.

Но, буквально, в следующем же абзаце:
When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.

Так-так-так, а что тут у нас? А тут написано, что единственное текстовое поле — это частный случай и нажатие клавиши ввода должно рассматриваться как отправка формы!

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

Короче, так как же решить проблему и не добавлять кнопку?

Очень просто, вставить в форму следующее:
<input type="submit" hidden/>

По-моему, пахнет лёгким бредом, но уж как есть.

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

#html #form #submit
🤩30👍234👎1
#заметка дня

Есть такой элемент — template. Название говорит само за себя: это шаблон.

Пишете в него некий HTML/SVG код, потом клонируете и вставляете куда вам надо.

На этом месте апологеты фреймворков ухмыльнулись, но вы же не одни на свете, да?


const content = template.content. firstElementChild.cloneNode(true);


Важно понимать, что содержимое шаблона — это фрагмент (обёртка над реальными нодами, если грубо), поэтому обращаться с ним надо соответственно.

Почему для этой цели не использовать просто скрытый div или — привет из прошлого — script type="text/template"?

Ну второе вообще не в кассу, это просто абьюз. А первое:
- Контент внутри темплейта не будет загружаться, пока не склонирован явно: ни картинки, ни стили, ни скрипты
- Валидатор игнорирует содержимое, хоть dd храните там, хоть td
- Поисковые системы знают про template и точно не индексируют. А с div hidden всё не так однозначно.
- Ну и именование говорит само за себя. Сахар все любят.

#html #template #бородач
👍113
#фишка дня

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

Места на экране мало, ещё и клавиатура съест.

Очень просто! Использовать атрибут enterkeyhint!

Спека: https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-enterkeyhint-attribute

Поддержка: https://caniuse.com/?search=enterkeyhint

Пользуемся!

#mobile #form #html #бородач
👍301
#статья дня

Пришло время вспомнить ещё одну статью Ахмада Шадида (Ahmad Shadeed, который не раз всплывал здесь и ещё много раз всплывёт). На этот раз – о важности учитывания высоты в разработке сайтов.

https://ishadeed.com/article/responsive-design-height/

Разработчики часто забывают, что посетители редко используют весь доступный экран. Не только по ширине, но и по высоте. А мода в современных макетах диктует вольготное использование вертикального пространства, но с обязательным условием: “Всё должно влезать в один экран!”. Это, коненчо, бред, но мода есть мода.

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

Статья есть в переводе на Хабре: https://habr.com/ru/company/skillfactory/blog/524996/

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

#css #html #перевод #бородач
7👍7
#фишка дня

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

Буквально — используя параметры строки запроса (query string parameters).

Ну то есть что-то вроде https://buy.that?title=Product&action=buy&config=2&amount=3, классические GET-параметры, но управляемые с фронта.

А вот как позволить клиенту обновить страницу, сохранив эти параметры? Желательно, без лишней работы и без использования JS вообще.

А очень просто!

<a href="">Reload</a>

Да, вот так просто! Самое классное, что абсолютно валидно и есть в спеках: https://stackoverflow.com/questions/5637969/is-an-empty-href-valid/43340108#43340108

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

Не пишите лишнего, котаны!

#http #html #trick #бородач
22👍19
#заметка дня

#css #html #pp #pixelperfect

Один из самых проблемных вопросов верстальщиков — не обязательно начинающих — это так называемый “пиксель пёрфект” (pixel perfect). Проще говоря, свёрстанный макет должен полностью соответствовать дизайну вплоть до последнего пикселя.

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

Но всё немного интереснее.

Давайте сразу определимся: правильно свёрстанный макет точен до пикселя по умолчанию. Точка.

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

У блока стоят поля и отступы по 16 пикселей? Нет ни одной причины ставить 10, чтобы “было легче считать” (и такое бывает), а потом проходить по всему макету заново. Ставьте сразу 16, а чтобы помочь себе — пользуйтесь расширениями для браузера, например https://www.welldonecode.com/perfectpixel/

Конечно, так можно дойти до крайности. Я много раз видел как люди бездумно копируют размеры из Sketch, Avocode или Figma наивно полагая, что уж кому как не им знать о размерах и положении. Это самая большая ошибка, и я уж молчу о том, что редакторы зачастую ставят абсолютное позиционирование всему подряд.

Будьте заранее готовы к тому, что макет – живой. Выделенный блок делится на секции? Используйте проценты во флексах или fr в гридах, делите его относительными единицами. Дизайнер поставил 63 px? Это явно дрогнула рука, не используйте нечётные значения никогда, округляйте до ближайших x4 (в данном случае — 64). Во всех размерах должна просматриваться логика, не могут три кнопки в ряду иметь один размер, а четвёртая – другой.

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

В скором времени я попробую затронуть тему вёрстки изначально неудобных макетов: что делать если вам выдали макет в 1920 пикселей, а большинство ноутбуков до сих пор имеют 1366 и как вести диалог с дизайнером и заказчиком в такой ситуации.
34👍9🤩1
#заметка дня

Сразу с панча: не используйте input[type=“number”].

Он тащит за собой целый ворох проблем:

1. странно выглядит (ниже о том, почему);
2. плохо стилизуется;
3. не подчиняется стандартным атрибутам вроде maxlength (sick!);
4. имеет ARIA-роль spinbutton (ниже поясню, что это);
5. позволяет ввести e (10e9) и валидация даже не заикнётся;
6. в старых Safari и Chrome округляет введённые числа (например, номер кредитки) до мантиссы и экспоненты (по-моему, это уже конец);
7. во время ввода можно случайно нажать стрелку вверх или вниз (или даже тронуть колесо мышки на некоторых ос) и введённое число изменится.

Как видите, минусов немало. А откуда они вообще взялись?

А всё просто: input[type=“number”] создавался для имитации т. н. tally counter, ручного счётчика. Ну вы наверняка видели фильмы, где людей или скот считали надетым на палец устройством. Отсюда и ARIA-роль spinner (счётчик оборотов), и стрелки ввода.

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

Так что же делать?

А делать следующее:

<input type="text" inputmode="numeric" pattern="[0-9]*">

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

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

За подробностями можно обратиться к блогу разработчиков официального сайта правительства Великобритании: https://technology.blog.gov.uk/2020/02/24/why-the-gov-uk-design-system-team-changed-the-input-type-for-numbers/

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

Я помню подобное было у многих государственных сайтов,. но почти все блоги исчезли со временем...

Подытожим: input[type=“number”] делался не для того, как его применяют.

Подумайте об этом.

#css #html #number #aria #semantics #a11y #бородач
👍364🤩3
#фишка дня

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

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

Но не все знают, что лейбл можно повесить и на элемент button: https://codepen.io/alinaki/pen/XWjLedQ

Да, возможно, кнопке свой ярлык не нужен и даже MDN сообщает нам об этом, но!

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

Лейблом можно продублировать кнопку без внесения лишней когнитивной нагрузки (но не стоит, фокус он не примет). Пожалуй, для каких-нибудь игровых интерфейсов вполне может быть приемлемо.

А вот если вы не используете кнопки и балуетесь role=“button” на div-ах (в лучшем случае) — этой возможности вы лишены в принципе.

#html #button #label #бородач
4
#фишка дня

Давайте что-нибудь наболевшее.

Вот, например, если установить атрибут translate="no" на тег, содержащий название компании, то он не подвергнется автоматическому переводу (типа Google Translate): https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/translate

Удобно, если ваша компания называется "Clean Beam" или ещё какая-то подобная глупость.

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

#html #attribute #translate
19
#фишка дня

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

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

Но не все знают, что лейбл можно повесить и на элемент button: https://codepen.io/alinaki/pen/XWjLedQ

Да, возможно, кнопке свой ярлык не нужен и даже MDN сообщает нам об этом, но!

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

Лейблом можно продублировать кнопку без внесения лишней когнитивной нагрузки (но не стоит, фокус он не примет). Пожалуй, для каких-нибудь игровых интерфейсов вполне может быть приемлемо.

А вот если вы не используете кнопки и балуетесь role=“button” на div-ах (в лучшем случае) — этой возможности вы лишены в принципе.

#html #button #label #бородач
👍12
#инструмент дня

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

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

Тогда я воспользовался https://github.com/cheeriojs/cheerio, написав простой скрипт на node.js. Это похоже на реализацию селекторов в jQuery, но для Node.js. Разобрал данные и сохранил в JSON.

Оказывается, есть и более кондовые утилиты.

Например, https://github.com/mgdm/htmlq и https://stedolan.github.io/jq

Первый, как нетрудно догадаться, может обработать HTML, а второй — JSON. И всё из командной строки :)

Например, найти все ссылки на странице:

curl --silent https://www.rust-lang.org/ | htmlq --attribute href a


Можно и просто целые куски HTML выдирать, и селекторы использовать. А дальше — все возможности командной строки и скриптов для обработки.

Ну а jq может стать частью вашей CI/CD системы, разгребсти ответы от API GitHub, например, и выдать их в читаемом виде.

#tools #html #json #cli #бородач
👍9
#рекомендация дня

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

Есть ребята из компании 53xapps, занимаются созданием сайтов и автоматизацией бизнеса. Ну и вот они решили запилить свой собственный курс по Frontend разработке.

Конкретно: введение в алгоритмы, HTML/CSS, JavaScript и Vue.js.

Разработка курса заняла около полугода. Большое количество видео и практики.

Подход к обучению немного отличается от других курсов: сперва несколько уроков вас учат понимать алгоритмы и рисовать блок-схемы. После этого обучение становится более осмысленным.

Курс довольно плотный, тестовые студенты проходили его по 15-20 часов в неделю 4 месяца, но сейчас есть возможность проходить курс в спокойном собственном темпе. Все для вас 🙂

Освоите JavaScript, HTML/CSS, Vue.js. Познакомитесь с несколькими популярными библиотеками. Для старта во фронте вполне достаточно.

Есть несколько бесплатных уроков, можно попробовать и пощупать.

Итак, цена. 5000 рублей. А подписчикам канала промокод HTMLSHIT даст 1000 рублей скидки.

Программа курса и бесплатные уроки доступны по ссылке.

#frontend #HTML #CSS #JavaScript
🤡11👍82
#день_рождения дня

Сегодня День рождения не только лишь у меня, но и у HTML тегов!

29 октября 1991 года Тим Бернерс-Ли выкатил документ с названием HTML Tags.

И состоял он из описания 18 первых тегов: <title>, <nextid>, <a>, <isindex>, <plaintext>, <listing>, <p>, <h1>…<h6>, <address>, <hp1>, <hp2>…, <dl>, <dt>, <dd>, <ul>, <li>,<menu> и <dir>.

Архивная версия: https://www.w3.org/History/19921103-hypertext/hypertext/WWW/MarkUp/Tags.html

С Днём рождения, HTML! Ну и я :)

#html
🤩2811👍1
Media is too big
VIEW IN TELEGRAM
#ссылка дня

Сегодня день такой, про SVG-фильтры.

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

Ну, вниманием они обделены не только со стороны сообщества веб-разработчиков, но и немного со стороны разработчиков браузеров. У WebGL и WebGPU перспективы шире.

Но это не означает, что у SVG-фильтров нет козырей в рукаве! Один из самых важных — их можно применить прямо на HTML-элемент и он как работал, так и будет работать!

Естественно, этим пользуется не только Ана Тюдор (кстати, не пользуется, она не работает как разработчик, только как художник в этом смысле и консультант).

Глядите, какая демка: https://svg-shaders.vercel.app/
И её код: https://github.com/shuding/svg-shaders

Она позволяет с лёгкостью или нагенерировать нужных фильтров, или вообще принять идею для своих проектов.

Повторю: HTML-элементы продолжают работать как работали и это в разы проще, чем спользовать решения на Three.js.

Кстати, прикольный и уместный вариант использования SVG-фильтров на контенте мы с вами уже наблюдали на примере... PornHub: https://t.me/htmlshit/1416

#svg #filters #html #shaders
👍52
#такое дня

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

Теперь в 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
#фишка дня

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

Буквально — используя параметры строки запроса (query string parameters).

Ну то есть что-то вроде https://buy.that?title=Product&action=buy&config=2&amount=3, классические GET-параметры, но управляемые с фронта.

А вот как позволить клиенту обновить страницу, сохранив эти параметры? Желательно, без лишней работы и без использования JS вообще.

А очень просто!

<a href="">Reload</a>

Да, вот так просто! Самое классное, что абсолютно валидно и есть в спеках: https://stackoverflow.com/questions/5637969/is-an-empty-href-valid/43340108#43340108

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

Не пишите лишнего, котаны!

#http #html #trick #бородач
👍214🤩1