Gemini对话页面UI优化:1.更宽排版展示AI回答 2.输入框压扁释放竖向空间 3.AI回答红绿配色
// ==UserScript==
// @name Gemini-UI-Optimizer
// @namespace https://example.com/efficient-lazy-panda
// @match *://claude.ai/*
// @match *://chatgpt.com/*
// @match *://gemini.google.com/*
// @version 1.4
// @author Efficient Lazy Panda
// @license MIT
// @description Gemini对话页面UI优化:1.更宽排版展示AI回答 2.输入框压扁释放竖向空间 3.AI回答红绿配色
// ==/UserScript==
(function () {
'use strict';
// Detect which platform we're on
const isGemini = window.location.hostname.includes('gemini.google.com');
const isClaude = window.location.hostname.includes('claude.ai');
const isChatGPT = window.location.hostname.includes('chatgpt.com');
// Create a style element
const style = document.createElement('style');
// Common font styles for all platforms
const commonFontStyles = `
/* Common normalized font styles */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
}
`;
// Set platform-specific CSS
if (isGemini) {
style.textContent = commonFontStyles + `
/* Gemini wide screen CSS */
.chat-window,
.chat-container,
.conversation-container,
.gemini-conversation-container {
max-width: 95% !important;
width: 95% !important;
}
.input-area-container,
textarea,
.prompt-textarea,
.prompt-container {
max-width: 95% !important;
width: 95% !important;
}
textarea {
width: 100% !important;
}
.max-w-3xl,
.max-w-4xl,
.max-w-screen-md {
max-width: 95% !important;
}
.message-content,
.user-message,
.model-response {
width: 100% !important;
max-width: 100% !important;
}
.pre-fullscreen {
height: auto !important;
}
.input-buttons-wrapper-top {
right: 8px !important;
}
/* ==========================================================
* Gemini Input Area Compression (Single Row)
* ========================================================== */
/* Make the main fieldset a flex row */
.input-area-container fieldset,
/* =========================================================
🚀 GEMINI INPUT AREA COMPRESSION - PERFECT FIX 🚀
Based on Grid override: .text-input-field -> [ .leading-actions-wrapper, .text-input-field_textarea-wrapper, .trailing-actions-wrapper ]
========================================================= */
/* 1. Reset the grid container to a horizontal flex row */
.text-input-field {
display: flex !important;
flex-direction: row !important;
align-items: flex-end !important; /* Align to bottom so buttons don't float if text gets tall */
flex-wrap: nowrap !important;
padding: 4px 8px !important;
min-height: 48px !important;
}
/* 2. Left Side (Plus button, Tool drawer) */
.text-input-field > .leading-actions-wrapper {
order: 1 !important;
position: static !important;
display: flex !important;
flex-direction: row !important;
align-items: center !important;
height: auto !important;
margin-bottom: 4px !important; /* Align with bottom */
margin-right: 4px !important;
}
/* 3. Middle (The Input Text Box Wrapper) */
.text-input-field > .text-input-field_textarea-wrapper {
order: 2 !important;
position: static !important;
flex: 1 1 auto !important; /* Grow to take remaining space */
width: auto !important;
display: flex !important;
align-items: stretch !important;
margin: 0 !important;
padding: 0 !important;
}
/* The actual editor textarea */
rich-textarea .ql-editor {
flex: 1 1 auto !important;
min-height: 28px !important;
max-height: 250px !important; /* Auto-grow limit */
padding: 8px 12px 8px 105px !important; /* Shift cursor right by 95px to avoid overlap */
margin: 0 !important;
overflow-y: auto !important;
}
/* Hide the placeholder text ("问问 Gemini") */
rich-textarea .ql-editor.ql-blank::before,
rich-textarea .ql-editor::before {
display: none !important;
content: none !important;
color: transparent !important;
}
/* Hide the text label "工具" (Tools) while keeping the icon */
.toolbox-drawer-button .mdc-button__label span,
.toolbox-drawer-button span:not(.mat-icon):not(.mat-mdc-button-persistent-ripple):not(.mat-mdc-button-touch-target) {
display: none !important;
}
/* 4. Right Side (Pro button, Send button, Mic) */
.text-input-field > .trailing-actions-wrapper {
order: 3 !important;
position: static !important;
display: flex !important;
flex-direction: row !important;
align-items: center !important;
height: auto !important;
margin-bottom: 4px !important;
margin-left: 4px !important;
}
/* Hide disclaimer and any bottom spacer */
.footer-privacy-notice-link,
div:has(> a.footer-privacy-notice-link),
.disclaimer-container,
.footer-text,
hallucination-disclaimer {
display: none !important;
}
/* Reduce bottom padding of chat history since input area is much smaller */
.conversation-container,
.chat-history,
[class*="response-container"] {
padding-bottom: 24px !important;
}
/* ==========================================================
* Hide Top Bar to reclaim vertical space
* ========================================================== */
/* Google One Bar outer container + buffer spacer */
div.boqOnegoogleliteOgbOneGoogleBar,
div.desktop-ogb-buffer,
#gb {
display: none !important;
height: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
}
/* Gemini app top bar (conversation title, upgrade button, etc.) */
.top-bar-actions,
.conversation-title-container,
header.gmat-headline-4,
div[class*="top-bar"] {
display: none !important;
height: 0 !important;
overflow: hidden !important;
}
/* Hide the original Gemini text */
span[data-test-id="bard-text"] {
display: none !important;
}
/* Style for the relocated title */
#relocated-conv-title {
color: #aaa !important;
font-size: 14px !important;
font-weight: normal !important;
white-space: nowrap !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
max-width: 250px !important;
}
/* ==========================================================
* Heading colors in Gemini responses
* ========================================================== */
.response-container h2,
.model-response-text h2,
message-content h2 {
color: rgb(158, 8, 8) !important;
}
.response-container h3,
.model-response-text h3,
message-content h3 {
color: rgb(158, 8, 8) !important;
}
.response-container ol li::marker,
.model-response-text ol li::marker,
message-content ol li::marker,
.response-container ul li::marker,
.model-response-text ul li::marker,
message-content ul li::marker {
color: rgb(0, 128, 0) !important;
}
.response-container hr,
.model-response-text hr,
message-content hr {
border-color: rgb(158, 8, 8) !important;
}
.response-container b,
.model-response-text b,
message-content b {
color: rgb(0, 128, 0) !important;
}
/* Reset all text to normal weight (no bold) */
.response-container *,
.model-response-text *,
message-content * {
font-weight: normal !important;
}
`;
} else if (isClaude) {
style.textContent = commonFontStyles + `
/* Claude wide screen CSS */
.max-w-screen-md, .max-w-3xl, .max-w-4xl {
max-width: 95% !important;
}
.w-full.max-w-3xl, .w-full.max-w-4xl {
max-width: 95% !important;
width: 95% !important;
}
.w-full.max-w-3xl textarea {
width: 100% !important;
}
.mx-auto {
max-width: 95% !important;
}
[data-message-author-role] {
width: 100% !important;
}
.absolute.right-0 {
right: 10px !important;
}
/* Claude specific font fixes */
p, h1, h2, h3, h4, h5, h6, span, div, textarea, input, button {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
font-weight: 400 !important;
}
/* Fix for code blocks */
pre, code, .font-mono {
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important;
}
/* Fix for chat messages */
[data-message-author-role] p {
font-size: 16px !important;
line-height: 1.5 !important;
letter-spacing: normal !important;
}
/* Remove serif from headings */
h1, h2, h3, h4, h5, h6 {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important;
}
`;
} else if (isChatGPT) {
style.textContent = commonFontStyles + `
/* ChatGPT wide screen CSS - Updated for 2024/2025 */
/* Main container selectors */
.mx-auto,
.max-w-3xl,
.max-w-4xl,
.max-w-2xl,
.max-w-screen-md {
max-width: 95% !important;
width: 95% !important;
}
/* Chat container */
main {
max-width: 95% !important;
width: 95% !important;
}
/* Conversation container */
[role="main"],
.conversation,
.chat-container {
max-width: 95% !important;
width: 95% !important;
}
/* Message containers */
.group,
.text-base,
.gap-4,
.md\\:gap-6 {
max-width: 100% !important;
width: 100% !important;
}
/* Input area */
.stretch,
.flex-1,
.textarea,
textarea {
width: 100% !important;
max-width: 100% !important;
}
/* Form container */
form {
width: 100% !important;
max-width: 95% !important;
}
/* Chat message wrapper */
.w-full {
width: 100% !important;
max-width: 100% !important;
}
/* Specific class combinations that ChatGPT uses */
.flex.flex-col.pb-2,
.flex.w-full.flex-col,
.relative.flex.w-full.flex-col {
width: 100% !important;
max-width: 100% !important;
}
/* Override any fixed width containers */
[class*="max-w-"] {
max-width: 95% !important;
}
/* Ensure message content uses full width */
.prose {
max-width: 100% !important;
}
/* Input field specific styling */
[data-id] textarea,
[contenteditable="true"] {
width: 100% !important;
max-width: 100% !important;
}
/* Button container adjustments */
.absolute.bottom-0.right-0,
.absolute.right-0 {
right: 8px !important;
}
/* Responsive adjustments */
@media (min-width: 768px) {
.md\\:max-w-2xl,
.md\\:max-w-3xl,
.md\\:max-w-4xl {
max-width: 95% !important;
}
}
@media (min-width: 1024px) {
.lg\\:max-w-2xl,
.lg\\:max-w-3xl,
.lg\\:max-w-4xl {
max-width: 95% !important;
}
}
@media (min-width: 1280px) {
.xl\\:max-w-3xl,
.xl\\:max-w-4xl {
max-width: 95% !important;
}
}
`;
}
// Append the style element to the document head
document.head.appendChild(style);
// Function to apply wide mode to inline styles (especially for Gemini)
function applyWideModeToInlineStyles() {
if (!isGemini) return; // Only needed for Gemini
// Find elements with inline styles containing max-width
const elements = document.querySelectorAll('[style*="max-width"]');
elements.forEach(el => {
// Skip elements that might be side panels or navigation
if (el.classList.contains('side-panel') ||
el.classList.contains('navigation-panel')) {
return;
}
// Set max-width to 95%
el.style.maxWidth = '95%';
});
}
// Function to ensure Gemini's nested toolbar divs are 'unwrapped'
function optimizeGeminiInputLayout() {
if (!isGemini) return;
const fieldsets = document.querySelectorAll('fieldset');
for (const fs of fieldsets) {
const bottomBars = fs.querySelectorAll(
'.input-area-bottom-content, .input-buttons-container'
);
for (const bar of bottomBars) {
bar.style.display = 'contents';
}
}
}
// Function to relocate the conversation title to the Gemini logo area
function relocateConversationTitle() {
if (!isGemini) return;
// Find the conversation title using exact data-test-id
const titleEl = document.querySelector('span[data-test-id="conversation-title"]');
if (!titleEl) return;
const titleText = titleEl.textContent.trim();
if (!titleText) return;
// Find the Gemini logo text using exact data-test-id
const geminiText = document.querySelector('span[data-test-id="bard-text"]');
if (!geminiText) return;
// Check if we already injected the title
let relocated = document.getElementById('relocated-conv-title');
if (relocated) {
if (relocated.textContent !== titleText) {
relocated.textContent = titleText;
}
return;
}
// Create and inject the title element right in place of the Gemini text
relocated = document.createElement('span');
relocated.id = 'relocated-conv-title';
relocated.textContent = titleText;
geminiText.parentElement.insertBefore(relocated, geminiText.nextSibling);
}
// ChatGPT specific dynamic width application
function applyChatGPTWideMode() {
if (!isChatGPT) return;
// Target common ChatGPT container classes
const selectors = [
'.mx-auto',
'.max-w-3xl',
'.max-w-2xl',
'.max-w-4xl',
'main',
'[role="main"]',
'.conversation',
'form'
];
selectors.forEach(selector => {
const elements = document.querySelectorAll(selector);
elements.forEach(el => {
if (!el.classList.contains('sidebar') &&
!el.classList.contains('menu') &&
!el.parentElement?.classList.contains('sidebar')) {
el.style.maxWidth = '95%';
el.style.width = '95%';
}
});
});
// Handle input areas specifically
const inputElements = document.querySelectorAll('textarea, [contenteditable="true"]');
inputElements.forEach(el => {
el.style.width = '100%';
el.style.maxWidth = '100%';
});
}
// Apply the changes when the DOM is fully loaded
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', function () {
applyWideModeToInlineStyles();
optimizeGeminiInputLayout();
relocateConversationTitle();
applyChatGPTWideMode();
});
} else {
applyWideModeToInlineStyles();
optimizeGeminiInputLayout();
relocateConversationTitle();
applyChatGPTWideMode();
}
// Create a MutationObserver to watch for dynamically added elements
if (isGemini) {
const observer = new MutationObserver(function (mutations) {
applyWideModeToInlineStyles();
optimizeGeminiInputLayout();
relocateConversationTitle();
});
// Start observing the document body for changes
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['style', 'class']
});
}
// Enhanced ChatGPT observer
if (isChatGPT) {
const chatGPTObserver = new MutationObserver(function (mutations) {
if (chatGPTObserver.timeoutId) {
return;
}
chatGPTObserver.timeoutId = setTimeout(function () {
applyChatGPTWideMode();
delete chatGPTObserver.timeoutId;
}, 300);
});
// Observe the entire document for ChatGPT changes
chatGPTObserver.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['class', 'style']
});
}
// Claude observer (keeping original logic)
if (isClaude) {
const claudeObserver = new MutationObserver(function (mutations) {
if (claudeObserver.timeoutId) {
return;
}
claudeObserver.timeoutId = setTimeout(function () {
const inputElements = document.querySelectorAll('textarea, [role="textbox"], div[contenteditable="true"]');
inputElements.forEach(el => {
if (el && !el.dataset.widthFixed) {
el.style.width = '100%';
el.style.maxWidth = '100%';
el.dataset.widthFixed = 'true';
}
});
delete claudeObserver.timeoutId;
}, 500);
});
const formElement = document.querySelector('form') || document.body;
claudeObserver.observe(formElement, {
childList: true,
subtree: true,
attributes: false
});
}
})();