第14章 自定义用户界面
到这里,你的应用已经能跑了。但看起来可能还像个原型。
没问题。功能优先于装饰。交互跑通之后,再去打磨视觉呈现。
想让界面更精致,并不需要把 Gradio 应用改造成一个庞大的前端工程。
Gradio 提供了多种来自定义用户体验的方式。
标题与描述
从清晰的元数据开始。
demo = gr.ChatInterface(
fn=respond,
title="Study Buddy",
description="Ask questions and learn interactively."
)
标题告诉用户这是什么应用,描述则说明用户能做什么。
Markdown 标题
你还能用 Markdown 来组织 Blocks 应用的结构:
with gr.Blocks() as demo:
gr.Markdown("# Study Buddy")
gr.Markdown(
"Ask questions about programming, mathematics, and science."
)
说明比装饰更重要
设计再漂亮,用户也可能看不懂该怎么用。
对比一下:
gr.Textbox()
和:
gr.Textbox(
label="Question",
placeholder="Ask a question about Python..."
)
第二种写法传达了期望的交互方式。好的 UX 从措辞开始。
主题
Gradio 支持主题,可以统一影响组件的外观。
构建应用时即可指定主题。
例如:
with gr.Blocks(theme=gr.themes.Soft()) as demo:
...
主题能提供一个统一的视觉基础,无需逐个组件手动设置样式。
别随便选主题
主题应与应用定位相匹配。
开发者工具适合简洁克制的界面,创意生图应用可以用更具表现力的设计,教育类应用则应优先考虑可读性。
目的不是让它看起来花哨,而是让用起来简单、舒服。
自定义 CSS
Gradio 也支持在合适的配置项中使用自定义 CSS。
例如:
custom_css = """
body {
font-family: sans-serif;
}
"""
然后:
with gr.Blocks(css=custom_css) as demo:
...
CSS 能带来更强的控制力,但也增加了维护成本。
为什么不要滥用自定义 CSS
如果你大量依赖内部组件的类名或实现细节,Gradio 升级后样式可能会失效。
尽量优先使用稳定的、有文档说明的自定义机制,只在真正需要时才用自定义 CSS。
组件尺寸
组件占用的空间通常是可以控制的。
例如:
gr.Textbox(
lines=10
)
会生成一个更大的文本区域。
布局比例参数也很有用:
with gr.Row():
with gr.Column(scale=2):
...
with gr.Column(scale=1):
...
按钮变体
按钮可以体现操作的层级关系。
例如:
gr.Button(
"Generate",
variant="primary"
)
可以用来表示主要操作。
次要操作在支持的情况下可以使用不那么醒目的样式。
不要把所有按钮都设为主按钮
如果每个按钮在视觉上都很突出,就没有哪个能清晰表达“这是主要操作”。
把更强的视觉强调留给最重要的那个操作。
示例
Gradio 界面可以提供示例输入。
对图像分类器来说,示例能让用户知道适合输入什么样的图片;对文本生成器来说,示例可以展示有效的提示词。
示例能降低上手门槛。
无障碍
视觉设计不只是好看,界面还应让尽可能多的人都能使用。
需要考虑:
描述清晰的标签
易于阅读的文字
足够的对比度
合理的结构组织
不要只用颜色作为唯一标识
清晰的错误提示
不要依赖:
red = error
green = success
单独使用时,
应附上文字说明,例如:
Upload failed.
自适应界面
用户可能通过笔记本、台式机、平板或手机访问你的应用。
不要只针对某一种屏幕尺寸设计。可用宽度变化时,布局仍应保持清晰易读。
隐藏高级选项
如果应用包含技术参数,不必一开始就全部展示。
可以用 Accordion 组件来收纳:
with gr.Accordion("Advanced Settings"):
temperature = gr.Slider(...)
max_tokens = gr.Number(...)
这样高级用户有操作空间,新手也不会被信息淹没。
品牌化
在为项目或组织开发应用时,你可能需要:
Logo
统一的标题
品牌色
字体排版
说明性文案
可以使用 Markdown 和支持的媒体组件来实现品牌化。
例如:
gr.Markdown("# My AI Assistant")
在合适的位置也可以用图片组件展示 Logo。
没必要把界面做得像网站
Gradio 非常适合构建交互式 Python 应用。
如果你想复刻一个带复杂导航、动画和自定义前端交互的大型营销网站,Gradio 可能不是合适的选择。
把 Gradio 用在它擅长的地方:围绕 Python 函数和模型的交互式应用。
自定义 HTML
有特定展示需求时可以使用 HTML。
例如:
gr.HTML(
"<h2>Welcome to the application</h2>"
)
但如果只是不习惯用 Markdown 就转向 HTML,那大可不必。Markdown 通常更易维护。
应用描述
好的应用描述应回答以下问题:
这个应用是做什么的?
用户需要提供什么?
用户会收到什么?
例如:
gr.Markdown(
"""
# PDF Summarizer
Upload a PDF and receive a concise summary of its contents.
"""
)
这比下面这样更有用:
gr.Markdown("# Welcome!!!")
加载与进度反馈
用户应当能感知到系统正在运行。
如果模型需要十秒才返回结果,一个看起来卡死的界面只会让用户反复点击按钮。
Gradio 的事件和队列机制可以帮助传达进度并管理执行流程。
性能与生产环境的考量将在第 23 章展开。
错误提示
不要只显示:
Error
而应该写成:
The file could not be processed. Please upload a valid PDF.
错误提示应告诉用户哪里出了问题、能否自行修复、下一步该做什么。
空状态
想想用户在还没做任何操作时看到的是什么。一个空应用不应该让人觉得是出了故障。
一个有用的空状态提示可以这样写:
Upload a document to begin.
而不是放一个完全空白的结果面板。
示例:打磨过的文档分析器
import gradio as gr
def analyze_document(file):
if file is None:
return "Please upload a document."
return "The document would be analyzed here."
with gr.Blocks(
theme=gr.themes.Soft()
) as demo:
gr.Markdown(
"""
# Document Analyzer
Upload a document and analyze its contents.
"""
)
with gr.Row():
with gr.Column():
file = gr.File(
label="Document"
)
analyze_button = gr.Button(
"Analyze Document",
variant="primary"
)
with gr.Column():
result = gr.Textbox(
label="Analysis",
lines=12
)
analyze_button.click(
fn=analyze_document,
inputs=file,
outputs=result
)
demo.launch()
这段代码并不比前面的例子复杂多少,区别在于界面把自己的用途表达得更清楚了。
保持视觉一致性
如果你在应用的一处用了:
label="Input Text"
在另一处对同类交互却写成:
label="Enter Something"
界面就会显得不统一。
选定一种命名风格,然后坚持用下去。
不要为了好看牺牲易用性
避免使用过小的文字,也别用那种巨大的装饰性标题,把重要控件挤到屏幕外看不见的地方。
同时避免不必要的动画,也不要把重要操作藏在多层点击之后。
好的设计能让应用更好用。
动手试一试
选一个你之前写的应用,给它做一次视觉上的改造。
添加:
清晰的标题
有用的描述
主题
合理的分区
更好的标签
含义明确的按钮名称
高级设置区域
友好的空状态提示文字
除非确实需要,否则不要加自定义 CSS。目标是让应用看起来是精心设计的,而不仅仅是能用。
本章要点
好的 UI 始于清晰的语言和结构。
主题提供了便捷的视觉基础。
自定义 CSS 能带来更强的控制力,但应谨慎使用。
按钮层级能帮助用户识别主要操作。
示例能让不熟悉的应用更容易上手。
无障碍设计应与视觉设计一并考虑。
响应式布局很重要。
高级设置可以隐藏起来,等用户需要时再展示。
好的设计提升的是易用性,而不是单纯堆砌装饰。