Спойлер: коды готовы — вставьте и пользуйтесь.Знаете, что меня расстраивало больше всего в чатах с нейросетями? Сидишь, читаешь длинный ответ в момент генерации. Дошёл до середины, понял, что упустил какую-то деталь в начале, крутишь скролл вверх. А бот в этот момент дописывает новый абзац, и весь текст уезжает обратно вниз.Штатная стрелочка «наверх» тут не спасает. Она кидает к шапке сайта, а не к началу конкретного сообщения ассистента. Приходится ловить текст вручную. Сейчас стали выкатывать что-то вроде истории запросов справа от чата, похожее на закладки, но мне они не нравятся по той же причине: надо приглядываться и целиться в анимированный интерфейс.Чтобы не дергать страницу туда-сюда, я набросал около 10 юзерскриптов для всех популярных чатов. Они вешают в углу экрана кнопку, которая телепортирует прямо к первой строчке именно последнего ответа. Заодно вычищают визуальный мусор, который разработчики добавляют в интерфейс без возможности отключения штатными методами. Читать далее
Спойлер: коды готовы — вставьте и пользуйтесь.

Пример кнопки. Логотипы являются товарными знаками компаний.
Знаете, что меня расстраивало больше всего в чатах с нейросетями? Сидишь, читаешь длинный ответ в момент генерации. Дошёл до середины, понял, что упустил какую-то деталь в начале, крутишь скролл вверх. А бот в этот момент дописывает новый абзац, и весь текст уезжает обратно вниз.
Штатная стрелочка “наверх” тут не спасает. Она кидает к шапке сайта, а не к началу конкретного сообщения ассистента. Приходится ловить текст вручную. Сейчас стали выкатывать что-то вроде истории запросов справа от чата, похожее на закладки, но мне они не нравятся по той же причине: надо приглядываться и целиться в анимированный интерфейс.
Чтобы не дергать страницу туда-сюда, я набросал около 10 юзерскриптов для всех популярных чатов. Они вешают в углу экрана кнопку, которая телепортирует прямо к первой строчке именно последнего ответа. Заодно вычищают визуальный мусор, который разработчики добавляют в интерфейс без возможности отключения штатными методами.
Под капотом логика везде одинаковая. Скрипт ищет в DOM-дереве последний блок с ответом, рисует поверх всего кнопку с position: fixed, а по клику вызывает обычный scrollIntoView. Чтобы было понятно, куда именно мы прыгнули, блок на секунду подсвечивается. Можно придумать любые эффекты и доработки оригинального интерфейса. Я начал с кнопки, а потом решил почистить интерфейс.
Поскольку все эти чаты работают как SPA, просто повесить обработчик на загрузку страницы не получится. Приходится слушать изменения через MutationObserver, иначе при переходе в новый диалог кнопка отвалится.
Самое интересное начинается на этапе поиска нужного div. У каждой платформы свои заморочки.
В ChatGPT и Claude жизнь облегчает наличие нормальных data-* атрибутов или предсказуемых классов. Нашел [data-message-author-role="assistant"] — и можно расслабиться.
Честно говоря, я не сильно вникал в код. Как только видел, что кнопка работает, то переходил к настройке другого ИИ чата. Поэтому, если кому интересно сделать надёжнее, пишите в комментариях как улучшить код для уменьшения вероятности отвала после обновлений сайтов с чатами.
С Gemini и Grok тоже более-менее понятно: там либо веб-компоненты вроде model-response, либо обычные markdown-контейнеры.
А вот DeepSeek любит использовать хеш-классы. Сегодня ты ищешь сообщение по .ds-message, а завтра верстак обновился, и классы превратились в случайный набор букв. Приходится делать кучу фолбэков, как в Qwen, где скрипт перебирает несколько вариантов селекторов, пока не наткнется на нужный. В Perplexity вообще приходится искать контент внутри специфичных renderer-блоков.
Ниже полный рабочий userscript для ChatGPT.
// ==UserScript==
// @name ChatGPT
// @namespace http://tampermonkey.net/
// @version 1.5
// @description Кнопка к началу ответа на chatgpt.com
// @match https://chatgpt.com/*
// @grant none
// @run-at document-idle
// ==/UserScript==
(function() {
'use strict';
// Скрываем блоки CSS
const style = document.createElement('style');
style.textContent = `
/* Reasoning */
.reasoning,
.model-reasoning,
.thought,
.chain-of-thought,
[data-reasoning="true"],
[class*="reasoning"],
[class*="thought"] {
display: none !important;
}
.thinking-indicator,
.model-thinking {
display: none !important;
}
/* Follow-up suggestions */
p:has(+ ul[data-is-last-node][data-is-only-node]) {
display: none !important;
}
ul[data-is-last-node][data-is-only-node] {
display: none !important;
}
ul:has(li span.entity-underline) {
display: none !important;
}
p:has(span:contains("следующим шагом")) {
display: none !important;
}
.follow-up,
.suggestion,
.suggested-actions {
display: none !important;
}
/* Дисклеймер */
.text-caption-regular {
display: none !important;
}
[class*="text-token-text-tertiary"] .text-caption-regular {
display: none !important;
}
/* Кнопка "Принять предложение" */
div.mx-3\\.5.mt-1.mb-2:has(button[aria-label="Принять предложение"]) {
display: none !important;
}
`;
document.head.appendChild(style);
// Динамическое скрытие (для follow-up)
function hideUnwantedElements() {
document.querySelectorAll('ul[data-is-last-node][data-is-only-node]').forEach(el => {
el.style.display = 'none';
});
document.querySelectorAll('p:has(+ ul[data-is-last-node][data-is-only-node])').forEach(el => {
el.style.display = 'none';
});
document.querySelectorAll('p').forEach(el => {
if (el.textContent.includes('следующим шагом')) {
const next = el.nextElementSibling;
if (next && next.tagName === 'UL' && next.querySelector('span.entity-underline')) {
el.style.display = 'none';
next.style.display = 'none';
}
}
});
}
hideUnwantedElements();
const observer = new MutationObserver(() => {
hideUnwantedElements();
});
observer.observe(document.body, { childList: true, subtree: true });
// Поиск последнего ответа ассистента
function getLastAssistantMessage() {
const messages = document.querySelectorAll('[data-message-author-role="assistant"]');
if (messages.length > 0) {
return messages[messages.length - 1];
}
const turns = document.querySelectorAll('[data-turn="assistant"]');
if (turns.length > 0) {
return turns[turns.length - 1];
}
return null;
}
// Создание кнопки
const btn = document.createElement('button');
btn.textContent = 'К началу ответа'; // ← Текст кнопки (меняйте)
btn.title = 'Прокрутить к началу последнего ответа ИИ';
btn.style.cssText = `
position: fixed;
bottom: 28px; /* ← Отступ снизу */
right: 28px; /* ← Отступ справа */
z-index: 10000;
padding: 10px 18px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); /* ← Цвета градиента (меняйте) */
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 13px;
font-weight: 500;
box-shadow: 0 4px 14px rgba(102, 126, 234, 0.35);
transition: all 0.2s ease;
backdrop-filter: blur(6px);
`;
btn.onmouseenter = () => {
btn.style.transform = 'translateY(-2px)';
btn.style.boxShadow = '0 6px 18px rgba(102, 126, 234, 0.5)';
};
btn.onmouseleave = () => {
btn.style.transform = 'translateY(0)';
btn.style.boxShadow = '0 4px 14px rgba(102, 126, 234, 0.35)';
};
btn.onclick = () => {
const target = getLastAssistantMessage();
if (target) {
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
const origBorder = target.style.borderTop;
const origTrans = target.style.transition;
target.style.transition = 'border-top 0.2s ease';
target.style.borderTop = '3px solid #667eea'; // ← Цвет подсветки (меняйте)
setTimeout(() => {
target.style.borderTop = origBorder;
target.style.transition = origTrans;
}, 1500);
} else {
console.warn('[ChatGPT Scroll] Assistant message not found');
window.scrollTo({ top: 0, behavior: 'smooth' });
}
};
// Добавление кнопки в DOM
function initButton() {
if (document.body) {
document.body.appendChild(btn);
} else {
setTimeout(initButton, 100);
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initButton);
} else {
initButton();
}
// Поддержка SPA
let lastUrl = location.href;
new MutationObserver(() => {
const url = location.href;
if (url !== lastUrl) {
lastUrl = url;
if (!document.body.contains(btn)) {
initButton();
}
}
}).observe(document, { subtree: true, childList: true });
})();
Применить скрипт легко: Установите расширение Tampermonkey для вашего браузера. Нажмите на иконку Tampermonkey и “Создать новый скрипт”. Удалите всё в шаблоне и вставьте скрипт. Сохраните (Ctrl+S) и обновите страницу нужного чата. Наслаждайтесь кнопкой!
Расположение кнопки на разных экранах может отличаться. Если она встала не туда, то просто поправьте значения bottom и right в коде за 5 секунд.
Настройка под себя: Цвет кнопки - замените #667eea и #764ba2 на свои hex-коды. Расположение - поменяйте значения bottom и right. Текст кнопки - замените “К началу ответа” на что угодно. Скрытие подписей - удалите или закомментируйте строки с селекторами.
Минус у такого подхода со скриптами один — мы парсим чужую верстку. Как только платформа решает провести редизайн (вряд ли это будет очень часто) или просто меняет нейминг классов, то скрипт сразу же ломается и хеш-классы отваливаются первыми. Data-атрибуты живут дольше, но и они не вечны.
Это не история из разряда «поставил и забыл». Скорее, «поставил, пользуешься, пока не прилетит обновление от вендора». Но меня это устраивает. Для меня секундное дело зайти в DevTools и глянуть код.
Вчера как раз DeepSeek выкатил минорный апдейт, и кнопка исчезла. Пришлось открывать консоль, искать новый класс для блока с мыслями и править CSS. Зато теперь интерфейс снова не режет глаз, и я очень рад своему небольшому изобретению. Мелочь, а приятно!
Все скрипты кнопок для разных ИИ лежат у меня на GitHub: button-AI.
Коротко обо мне: я архитектор и дизайнер интерьера, и моя страсть к удобству распространяется не только на архитектурные пространства, но и на цифровые интерфейсы. Меня зовут Артём Ерыков. Если интересно — загляните на мой сайт. Буду рад познакомиться.