- PVSM.RU - https://www.pvsm.ru -
Здесь вы найдёте небольшую подборку нестандартных вариантов использования HTML/CSS/JS. Если информация окажется полезной, будем собирать эти хаки на постоянной основе и публиковать по мере накопления.
Примечание. Некоторые трюки основаны на открытых уязвимостях браузеров и поисковой системы Google и др. Поэтому могут перестать работать в ближайшее время (или продолжат, если разработчики не признают баги и не захотят их исправлять). Другие функции работают только начиная с конкретных версий Chrome, Firefox и т. д.
Маркетолог и SEO-оптимизатор Дэн Петрович нашёл способ [1], как отслеживать действия пользователей на сайтах конкурентов, включая полную информацию о просмотрах страниц, переходах по ссылкам, времени просмотра, видеозаписях сессий и нажатиях клавиш. Можно собирать всю информацию, которая вводится в веб-формы на чужом сайте, и получать её к себе по электронной почте. Всё это делается с помощью подделки чужого сайта и заманивания юзеров на это зеркало. Способ не совсем этичный, поэтому публикуем информацию исключительно в образовательных целях.
Алгоритм:
Примечание 1. Альтернативный способ заведения пользователей на зеркало чужого сайта — через поисковую рекламу. На самом деле в интернете полно фейковых копий (зеркал) аутентичных сайтов, в том числе Хабра, куда заходят тысячи пользователей из поиска, не подозревая о подделке.
Примечание 2. Несколько лет назад похожий способ использовался для перехвата звонков через публикацию фейковых объявлений на Google Maps со своим телефонным номером вместо оригинальных номеров ФБР и Секретной службы США.
В результате пользователи звонят по нашим номерам и сообщают информацию, которую хотели передать спецслужбам.
Нажатие кнопки DesignMode ON/OFF
делает веб-страницу редактируемой [2]. Нужна всего одна строчка JavaScript в коде:
document.designMode = "on";
Это древние API появились 25 лет назад, но до сих пор поддерживаются в браузерах.
В последние годы во многих браузерах появилась поддержка современных форматов сжатия изображений AVIF и WebP (к сожалению, 10 декабря 2022 года Google удалила [3] поддержку JPEG XL из Chromium, так что этот формат теперь не слишком актуален). Можно сократить трафик со своего сайта, если включить эту оптимизацию [4] с помощью тега <picture>
.
Идея в том, чтобы выдавать AVIF и WebP только тем браузерам, которые это поддерживают.
$ magick convert image.jpg image.avif
Аналогичную конвертацию производим для каждой пары форматов (jpg/avif, jpg/webp).
<img>
, прописываем тег <picture>
, который допускает перечисление нескольких URL для одной картинки. Первым указываем AVIF как самый маленький формат. Нормальные браузеры загрузят его, а Edge и все остальные, которые не поддерживают AVIF [7], пойдут дальше по списку: WebP и JPEG.
<picture>
<source srcset="/document.avif" type="image/avif">
<source srcset="/document.webp" type="image/webp">
<img src="/document.jpeg" alt="Скриншот" width="375" height="153" class="border">
</picture>
Все варианты указываем в теге <source>
, и только последний в теге <img>
.
<picture>
не оптимально грузить клиенту всё подряд. Лучше распознать браузерный юзер-агент и заранее пушить картинку соответствующего формата. Специально для этого предназначено поле Accept
в user-agent. Например, последний Firefox высылает Accept
такого вида:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8
Если у вас есть какое-то веб-приложение и вы хотите дать возможность людям работать в нём без авторизации на сайте и хранения данных на сервере, то для этого есть интересный хак: сохранять состояние в URL [9], в браузере клиента.
Это даёт возможность пользователю «сохраниться», а позже продолжить работу (редактирование данных). Также удобно делиться результатами работы с коллегами просто путём отправки URL.
Состояние приложения — файл JSON, он кодируется в строку, потом сжимается и переводится в байты Base64, которые добавляются в URL после символов `/g/a#`. Например, таким образом:
наш_сайт.com/g/a#N4IgzgpgTglghgGxgLwnARgiAxA9lAWxAC5QA7X...
Псевдокод для реализации такой функциональности:
const stateString = JSON.stringify(appState); // appState представляет собой объект JSON
const compressed = compress(stateString);
const encoded = Base64.encode(compressed);
// Пушим закодированную строку в url
// ...Позже при загрузке страницы или undo/redo читаем url и
// делаем следующее
const decoded = Base64.decode(encoded); // в той же кодировке, что и выше, но считывается из url
const uncompressed = uncompress(decoded);
const newState = JSON.parse(uncompressed);
// Загружаем приложение с новым состоянием newState
URL обновляется после каждого изменения состояния приложения, так что скопировать текущее состояние можно простым копипастом из адресной строки браузера. Примеры, как это работает: интерактивные редакторы блок-схем knotend [10] и mermaid.live [11]:
Есть несколько вариантов, как реализовать функции сжатия/декомпрессии, например, lz-stirng [12] или pako [13].
В качестве бонуса мы получаем для своего веб-приложения «бесплатную» функциональность undo/redo из браузерного стека, а также автоматическое внедрение на любую стороннюю веб-страницу, которая поддерживает embed'ы.
Можно ещё посмотреть, как Yahoo! Finance хранит настройки пользователя в URL:
https://finance.yahoo.com/quote/F/chart?p=F#eyJpbnRlcnZhbCI6IndlZWsiLCJwZXJpb2RpY2l0eSI6MSwidGltZVVuaXQiOm51bGwsImNhbmRsZVdpZHRoIjo0LjM0ODY1OTAwMzgzMTQxNzUsImZsaXBwZWQiOmZhbHNlLCJ2b2x1bWVVbmRlcmxheSI6dHJ1ZSwiYWRqIjp0cnVlLCJjcm9zc2hhaXIiOnRydWUsImNoYXJ0VHlwZSI6ImxpbmUiLCJleHRlbmRlZCI6ZmFsc2UsIm1hcmtldFNlc3Npb25zIjp7fSwiYWdncmVnYXRpb25UeXBlIjoib2hsYyIsImNoYXJ0U2NhbGUiOiJsaW5lYXIiLCJzdHVkaWVzIjp7IuKAjHZvbCB1bmRy4oCMIjp7InR5cGUiOiJ2b2wgdW5kciIsImlucHV0cyI6eyJpZCI6IuKAjHZvbCB1bmRy4oCMIiwiZGlzcGxheSI6IuKAjHZvbCB1bmRy4oCMIn0sIm91dHB1dHMiOnsiVXAgVm9sdW1lIjoiIzAwYjA2MSIsIkRvd24gVm9sdW1lIjoiI2ZmMzMzYSJ9LCJwYW5lbCI6ImNoYXJ0IiwicGFyYW1ldGVycyI6eyJ3aWR0aEZhY3RvciI6MC40NSwiY2hhcnROYW1lIjoiY2hhcnQifX19LCJwYW5lbHMiOnsiY2hhcnQiOnsicGVyY2VudCI6MSwiZGlzcGxheSI6IkYiLCJjaGFydE5hbWUiOiJjaGFydCIsImluZGV4IjowLCJ5QXhpcyI6eyJuYW1lIjoiY2hhcnQiLCJwb3NpdGlvbiI6bnVsbH0sInlheGlzTEhTIjpbXSwieWF4aXNSSFMiOlsiY2hhcnQiLCLigIx2b2wgdW5kcuKAjCJdfX0sInNldFNwYW4iOnsibXVsdGlwbGllciI6NSwiYmFzZSI6InllYXIiLCJwZXJpb2RpY2l0eSI6eyJwZXJpb2QiOjEsImludGVydmFsIjoid2VlayJ9fSwibGluZVdpZHRoIjoyLCJzdHJpcGVkQmFja2dyb3VuZCI6dHJ1ZSwiZXZlbnRzIjp0cnVlLCJjb2xvciI6IiMwMDgxZjIiLCJzdHJpcGVkQmFja2dyb3VkIjp0cnVlLCJldmVudE1hcCI6eyJjb3Jwb3JhdGUiOnsiZGl2cyI6dHJ1ZSwic3BsaXRzIjp0cnVlfSwic2lnRGV2Ijp7fX0sImN1c3RvbVJhbmdlIjpudWxsLCJzeW1ib2xzIjpbeyJzeW1ib2wiOiJGIiwic3ltYm9sT2JqZWN0Ijp7InN5bWJvbCI6IkYiLCJxdW90ZVR5cGUiOiJFUVVJVFkiLCJleGNoYW5nZVRpbWVab25lIjoiQW1lcmljYS9OZXdfWW9yayJ9LCJwZXJpb2RpY2l0eSI6MSwiaW50ZXJ2YWwiOiJ3ZWVrIiwidGltZVVuaXQiOm51bGwsInNldFNwYW4iOnsibXVsdGlwbGllciI6NSwiYmFzZSI6InllYXIiLCJwZXJpb2RpY2l0eSI6eyJwZXJpb2QiOjEsImludGVydmFsIjoid2VlayJ9fX1dfQ--
{"interval":"week","periodicity":1,"timeUnit":null,"candleWidth":4.3486590038314175,"flipped":false,"volumeUnderlay":true,"adj":true,"crosshair":true,"chartType":"line","extended":false,"marketSessions":{},"aggregationType":"ohlc","chartScale":"linear","studies":{" vol undr ":{"type":"vol undr","inputs":{"id":" vol undr ","display":" vol undr "},"outputs":{"Up Volume":"#00b061","Down Volume":"#ff333a"},"panel":"chart","parameters":{"widthFactor":0.45,"chartName":"chart"}}},"panels":{"chart":{"percent":1,"display":"F","chartName":"chart","index":0,"yAxis":{"name":"chart","position":null},"yaxisLHS":[],"yaxisRHS":["chart"," vol undr "]}},"setSpan":{"multiplier":5,"base":"year","periodicity":{"period":1,"interval":"week"}},"lineWidth":2,"stripedBackground":true,"events":true,"color":"#0081f2","stripedBackgroud":true,"eventMap":{"corporate":{"divs":true,"splits":true},"sigDev":{}},"customRange":null,"symbols":[{"symbol":"F","symbolObject":{"symbol":"F","quoteType":"EQUITY","exchangeTimeZone":"America/New_York"},"periodicity":1,"interval":"week","timeUnit":null,"setSpan":{"multiplier":5,"base":"year","periodicity":{"period":1,"interval":"week"}}}]}
Наверное, тут много лишней информации, но сам подход понятен.
Примечание. Поскольку браузеры могут обрезать слишком длинные URL, для данных целей надёжнее использовать стандарт URI-фрагментов [14] (строка после знака #
). Как говорится, всё новое — это хорошо забытое старое. Криптохостинг Mega.co.nz реализовал этот метод для передачи ключа расшифровки [15] ровно десять лет назад.
Пару лет назад Chrome реализовал интересный набор интерфейсов Reporting API [16], о котором до сих пор знают не все разработчики.
Через эти API браузер следит за пользователями вашего сайта и присылает отчёты по падениям/ошибкам с их стороны, просто отправляя JSON по указанному URL.
Правда, в данный момент в Chrome две несовместимые версии API [17], так что нужно разбираться, какую из версий лучше использовать.
Благодаря этим API можно найти нестандартные ошибки на своих страницах. Например, частые падения мобильных браузеров из-за CSS-анимаций [18]. Оказывается, стандартные CSS-анимации непосильны для старых смартфонов — браузер вылетает из-за недостатка RAM.
Если речь зашла о CSS, то пару месяцев назад все ведущие браузеры добавили поддержку тригонометрических функций [19].
Многие знают, что в свойствах объектов CSS можно использовать математические выражения [20]: от вычислений calc()
до логических функций min()
, max()
и clamp()
.
А начиная с версии Chrome 111, Firefox 108 и Safari 15.4 появилась ещё поддержка тригонометрических функций sin()
, cos()
, tan()
, asin()
, acos()
, atan()
и atan2()
. Все они описаны в спецификациях CSS Values and Units Module Level 4 [21].
Например, вот код [22] для вращения точки по кругу вокруг центральной точки:
:root {
--radius: 20vmin;
}
.dot {
--angle: 30deg;
translate: /* Translation on X-axis */
calc(cos(var(--angle)) * var(--radius))
/* Translation on Y-axis */
calc(sin(var(--angle)) * var(--radius) * -1)
;
}
Демо [22]:
Автор: Анатолий Ализар
Источник [23]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/384454
Ссылки в тексте:
[1] нашёл способ: https://dejanmarketing.com/competitor-hack/
[2] делает веб-страницу редактируемой: https://jfhr.me/document.designmode/
[3] удалила: https://chromium-review.googlesource.com/c/chromium/src/+/4081749
[4] включить эту оптимизацию: https://jfhr.me/optimizing-images-with-the-html-picture-tag/
[5] imagemagick: https://imagemagick.org/index.php
[6] avif.io: https://avif.io/
[7] Edge и все остальные, которые не поддерживают AVIF: https://caniuse.com/?search=avif
[8] HTTP/2 Server Push: https://en.wikipedia.org/wiki/HTTP/2_Server_Push
[9] сохранять состояние в URL: https://www.scottantipa.com/store-app-state-in-urls
[10] knotend: https://www.knotend.com/
[11] mermaid.live: https://mermaid.live/
[12] lz-stirng: https://github.com/pieroxy/lz-string
[13] pako: https://github.com/nodeca/pako
[14] URI-фрагментов: https://en.wikipedia.org/wiki/URI_fragment
[15] передачи ключа расшифровки: https://help.mega.io/security/data-protection/zero-knowledge-encryption
[16] Reporting API: https://developer.chrome.com/articles/reporting-api/
[17] две несовместимые версии API: https://developer.chrome.com/blog/reporting-api-migration/
[18] частые падения мобильных браузеров из-за CSS-анимаций: https://neugierig.org/software/blog/2023/01/browser-crashes.html
[19] тригонометрических функций: https://web.dev/css-trig-functions/
[20] математические выражения: https://web.dev/learn/css/functions/#mathematical-expressions
[21] CSS Values and Units Module Level 4: https://www.w3.org/TR/css-values-4/#trig-funcs
[22] вот код: https://codepen.io/web-dot-dev/pen/ExePgOg
[23] Источник: https://habr.com/ru/companies/ruvds/articles/731960/?utm_source=habrahabr&utm_medium=rss&utm_campaign=731960
Нажмите здесь для печати.