1. 其他教程
  2. 主题指南

主题

介绍

Gradio 具有内置的主题引擎,允许您自定义应用程序的外观和感觉。您可以从多种主题中选择,或创建自己的主题。为此,请将 theme= 关键字参数传递给 BlocksInterface 构造函数。例如:

with gr.Blocks(theme=gr.themes.Soft()) as demo:
    ...

Gradio 附带了一组预构建的主题,您可以从 gr.themes.* 加载。这些主题包括:

  • gr.themes.Base() - "base" 主题将主色调设置为蓝色,但除此之外几乎没有其他样式,因此特别适合作为创建新的自定义主题的基础。
  • gr.themes.Default() - 默认的 "default" Gradio 5 主题,具有鲜艳的橙色主色调和灰色次色调。
  • gr.themes.Origin() - "origin" 主题与 Gradio 4 的样式最为相似。颜色,尤其是在浅色模式下,比 Gradio 5 的默认主题更为柔和。
  • gr.themes.Citrus() - "citrus" 主题使用黄色作为主色调,突出显示处于焦点状态的表单元素,并在点击按钮时包含有趣的3D效果。
  • gr.themes.Monochrome() - "monochrome" 主题使用黑色作为主色,白色作为辅色,并使用衬线字体,呈现出黑白报纸的外观。
  • gr.themes.Soft() - "soft" 主题使用一种主要颜色和白色作为次要颜色。它还增加了按钮和表单元素周围的边框半径,并突出显示标签。
  • gr.themes.Glass() - "glass" 主题具有蓝色主色调和半透明灰色次色调。该主题还使用垂直渐变来创建玻璃效果。
  • gr.themes.Ocean() - "ocean" 主题具有蓝绿色主色调和灰色次色调。该主题还使用水平渐变,特别是用于按钮和一些表单元素。

每个主题都为数百个CSS变量设置了值。您可以使用预建主题作为自定义主题的起点,或者从头开始创建自己的主题。让我们来看看每种方法。

使用主题构建器

构建主题的最简单方法是使用主题构建器。要在本地启动主题构建器,请运行以下代码:

import gradio as gr

gr.themes.builder()

您可以使用上方Spaces上运行的Theme Builder,不过当您通过gr.themes.builder()在本地启动时,它的运行速度会快得多。

当您在主题构建器中编辑值时,应用程序将实时预览更新。您可以下载代码以生成您创建的主题,以便您可以在任何Gradio应用程序中使用它。

在本指南的其余部分,我们将介绍如何以编程方式构建主题。

通过构造函数扩展主题

尽管每个主题都有数百个CSS变量,但大多数这些变量的值都来自8个核心变量,这些变量可以通过每个预建主题的构造函数进行设置。修改这8个参数可以快速改变应用程序的外观和感觉。

核心颜色

前3个构造函数参数设置主题的颜色,并且是gradio.themes.Color对象。在内部,这些Color对象保存了单一色调调色板的亮度值,范围从50、100、200...、800、900、950。其他CSS变量是从这3种颜色派生的。

3个颜色构造函数参数是:

  • primary_hue: 这是主题中吸引注意力的颜色。在默认主题中,它被设置为 gradio.themes.colors.orange
  • secondary_hue: 这是用于主题中次要元素的颜色。在默认主题中,此颜色设置为 gradio.themes.colors.blue
  • neutral_hue: 这是用于主题中文本和其他中性元素的颜色。在默认主题中,这被设置为 gradio.themes.colors.gray

您可以使用它们的字符串快捷方式来修改这些值,例如

with gr.Blocks(theme=gr.themes.Default(primary_hue="red", secondary_hue="pink")) as demo:
    ...

或者你可以直接使用 Color 对象,像这样:

with gr.Blocks(theme=gr.themes.Default(primary_hue=gr.themes.colors.red, secondary_hue=gr.themes.colors.pink)) as demo:
    ...

预定义的颜色有:

  • slate
  • gray
  • zinc
  • neutral
  • stone
  • red
  • orange
  • amber
  • yellow
  • lime
  • green
  • emerald
  • teal
  • cyan
  • sky
  • blue
  • indigo
  • violet
  • purple
  • fuchsia
  • pink
  • rose

你也可以创建自己的自定义Color对象并传入。

核心尺寸

接下来的3个构造函数参数设置了主题的大小,并且是gradio.themes.Size对象。在内部,这些Size对象保存了从xxsxxl的像素大小值。其他CSS变量是从这3个大小派生出来的。

  • spacing_size: 这设置了元素内部和元素之间的间距。在默认主题中,这被设置为 gradio.themes.sizes.spacing_md
  • radius_size: 这设置了元素的圆角程度。在默认主题中,这被设置为 gradio.themes.sizes.radius_md
  • text_size: 这设置了文本的字体大小。在默认主题中,这被设置为 gradio.themes.sizes.text_md

您可以使用它们的字符串快捷方式来修改这些值,例如

with gr.Blocks(theme=gr.themes.Default(spacing_size="sm", radius_size="none")) as demo:
    ...

或者你可以直接使用 Size 对象,像这样:

with gr.Blocks(theme=gr.themes.Default(spacing_size=gr.themes.sizes.spacing_sm, radius_size=gr.themes.sizes.radius_none)) as demo:
    ...

预定义的大小对象有:

  • radius_none
  • radius_sm
  • radius_md
  • radius_lg
  • spacing_sm
  • spacing_md
  • spacing_lg
  • text_sm
  • text_md
  • text_lg

你也可以创建自己的自定义Size对象并传入。

核心字体

最后的2个构造函数参数设置了主题的字体。你可以为这些参数传递一个字体列表来指定备用字体。如果你提供一个字符串,它将被加载为系统字体。如果你提供一个gradio.themes.GoogleFont,字体将从Google Fonts加载。

  • font: 这设置了主题的主要字体。在默认主题中,这被设置为 gradio.themes.GoogleFont("IBM Plex Sans")
  • font_mono: 这设置了主题的等宽字体。在默认主题中,这被设置为 gradio.themes.GoogleFont("IBM Plex Mono")

你可以修改这些值,例如:

with gr.Blocks(theme=gr.themes.Default(font=[gr.themes.GoogleFont("Inconsolata"), "Arial", "sans-serif"])) as demo:
    ...

通过.set()扩展主题

你也可以在主题加载后修改CSS变量的值。为此,使用主题对象的.set()方法来访问CSS变量。例如:

theme = gr.themes.Default(primary_hue="blue").set(
    loader_color="#FF0000",
    slider_color="#FF0000",
)

with gr.Blocks(theme=theme) as demo:
    ...

在上面的例子中,我们将loader_colorslider_color变量设置为#FF0000,尽管整体的primary_color使用了蓝色调色板。你可以以这种方式设置主题中定义的任何CSS变量。

您的IDE类型提示应该帮助您浏览这些变量。由于有如此多的CSS变量,让我们来看看这些变量是如何命名和组织的。

CSS 变量命名规范

CSS变量名称可能会变得相当长,比如button_primary_background_fill_hover_dark!然而,它们遵循一种常见的命名约定,这使得理解它们的作用和找到你正在寻找的变量变得容易。变量名称由下划线分隔,由以下部分组成:

  1. 目标元素,例如 buttonsliderblock
  2. 目标元素类型或子元素,例如 button_primary,或 block_label
  3. 属性,例如 button_primary_background_fill,或 block_label_border_width
  4. 任何相关的状态,例如 button_primary_background_fill_hover
  5. 如果值在暗模式下不同,则后缀为_dark。例如,input_border_color_focus_dark

当然,许多CSS变量名称比这个更短,例如table_border_color,或input_shadow

CSS 变量组织

尽管有数百个CSS变量,但它们并不都需要有单独的值。它们通过引用一组核心变量并相互引用来获取值。这使得我们只需修改几个变量即可改变整个主题的外观和感觉,同时还能更精细地控制我们可能想要修改的单个元素。

引用核心变量

要引用核心构造函数变量之一,请在变量名前加上星号。要引用核心颜色,请使用*primary_*secondary_*neutral_前缀,后跟亮度值。例如:

theme = gr.themes.Default(primary_hue="blue").set(
    button_primary_background_fill="*primary_200",
    button_primary_background_fill_hover="*primary_300",
)

在上面的例子中,我们将button_primary_background_fillbutton_primary_background_fill_hover变量设置为*primary_200*primary_300。这些变量将分别设置为蓝色主色调板的200和300亮度值。

同样地,要引用核心尺寸,请使用*spacing_*radius_*text_前缀,后跟尺寸值。例如:

theme = gr.themes.Default(radius_size="md").set(
    button_primary_border_radius="*radius_xl",
)

在上面的示例中,我们将button_primary_border_radius变量设置为*radius_xl。此变量将设置为中等半径大小范围的xl设置。

引用其他变量

变量也可以相互引用。例如,请看下面的例子:

theme = gr.themes.Default().set(
    button_primary_background_fill="#FF0000",
    button_primary_background_fill_hover="#FF0000",
    button_primary_border="#FF0000",
)

必须将这些值设置为相同的颜色有点繁琐。相反,我们可以在button_primary_background_fill_hoverbutton_primary_border变量中引用button_primary_background_fill变量,使用*前缀。

theme = gr.themes.Default().set(
    button_primary_background_fill="#FF0000",
    button_primary_background_fill_hover="*button_primary_background_fill",
    button_primary_border="*button_primary_background_fill",
)

现在,如果我们更改button_primary_background_fill变量,button_primary_background_fill_hoverbutton_primary_border变量也会自动更新。

如果您打算分享您的主题,这将特别有用 - 它使得修改主题变得容易,而无需更改每个变量。

请注意,暗模式变量会自动相互引用。例如:

theme = gr.themes.Default().set(
    button_primary_background_fill="#FF0000",
    button_primary_background_fill_dark="#AAAAAA",
    button_primary_border="*button_primary_background_fill",
    button_primary_border_dark="*button_primary_background_fill_dark",
)

button_primary_border_dark 将从 button_primary_background_fill_dark 中获取其值,因为暗模式总是从变量的暗版本中获取。

创建一个完整的主题

假设你想从头开始创建一个主题!我们将一步一步地进行 - 你也可以在gradio源代码库中查看预建主题的源代码作为参考 - 这里是Monochrome主题的源代码

我们的新主题类将从gradio.themes.Base继承,这是一个设置了许多方便默认值的主题。让我们创建一个简单的演示,生成一个名为Seafoam的虚拟主题,并制作一个使用它的简单应用程序。

import gradio as gr
from gradio.themes.base import Base
import time

class Seafoam(Base):
    pass

seafoam = Seafoam()

with gr.Blocks(theme=seafoam) as demo:
    textbox = gr.Textbox(label="Name")
    slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
    with gr.Row():
        button = gr.Button("Submit", variant="primary")
        clear = gr.Button("Clear")
    output = gr.Textbox(label="Output")

    def repeat(name, count):
        time.sleep(3)
        return name * count

    button.click(repeat, [textbox, slider], output)

demo.launch()

基础主题非常简洁,并使用gr.themes.Blue作为其主要颜色 - 你会注意到主要按钮和加载动画因此都是蓝色的。让我们更改应用程序的默认核心参数。我们将覆盖构造函数并为核心构造函数参数传递新的默认值。

我们将使用gr.themes.Emerald作为我们的主色调,并将次要和中性色调设置为gr.themes.Blue。我们将使用text_lg来增大我们的文本。我们将使用从Google Fonts加载的Quicksand作为我们的默认字体。

from __future__ import annotations
from typing import Iterable
import gradio as gr
from gradio.themes.base import Base
from gradio.themes.utils import colors, fonts, sizes
import time

class Seafoam(Base):
    def __init__(
        self,
        *,
        primary_hue: colors.Color | str = colors.emerald,
        secondary_hue: colors.Color | str = colors.blue,
        neutral_hue: colors.Color | str = colors.gray,
        spacing_size: sizes.Size | str = sizes.spacing_md,
        radius_size: sizes.Size | str = sizes.radius_md,
        text_size: sizes.Size | str = sizes.text_lg,
        font: fonts.Font
        | str
        | Iterable[fonts.Font | str] = (
            fonts.GoogleFont("Quicksand"),
            "ui-sans-serif",
            "sans-serif",
        ),
        font_mono: fonts.Font
        | str
        | Iterable[fonts.Font | str] = (
            fonts.GoogleFont("IBM Plex Mono"),
            "ui-monospace",
            "monospace",
        ),
    ):
        super().__init__(
            primary_hue=primary_hue,
            secondary_hue=secondary_hue,
            neutral_hue=neutral_hue,
            spacing_size=spacing_size,
            radius_size=radius_size,
            text_size=text_size,
            font=font,
            font_mono=font_mono,
        )

seafoam = Seafoam()

with gr.Blocks(theme=seafoam) as demo:
    textbox = gr.Textbox(label="Name")
    slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
    with gr.Row():
        button = gr.Button("Submit", variant="primary")
        clear = gr.Button("Clear")
    output = gr.Textbox(label="Output")

    def repeat(name, count):
        time.sleep(3)
        return name * count

    button.click(repeat, [textbox, slider], output)

demo.launch()

看看主按钮和加载动画现在是不是绿色的?这些CSS变量与primary_hue变量相关联。

让我们更直接地修改主题。我们将调用set()方法来显式覆盖CSS变量值。我们可以使用任何CSS逻辑,并使用*前缀引用我们的核心构造函数参数。

from __future__ import annotations
from typing import Iterable
import gradio as gr
from gradio.themes.base import Base
from gradio.themes.utils import colors, fonts, sizes
import time

class Seafoam(Base):
    def __init__(
        self,
        *,
        primary_hue: colors.Color | str = colors.emerald,
        secondary_hue: colors.Color | str = colors.blue,
        neutral_hue: colors.Color | str = colors.blue,
        spacing_size: sizes.Size | str = sizes.spacing_md,
        radius_size: sizes.Size | str = sizes.radius_md,
        text_size: sizes.Size | str = sizes.text_lg,
        font: fonts.Font
        | str
        | Iterable[fonts.Font | str] = (
            fonts.GoogleFont("Quicksand"),
            "ui-sans-serif",
            "sans-serif",
        ),
        font_mono: fonts.Font
        | str
        | Iterable[fonts.Font | str] = (
            fonts.GoogleFont("IBM Plex Mono"),
            "ui-monospace",
            "monospace",
        ),
    ):
        super().__init__(
            primary_hue=primary_hue,
            secondary_hue=secondary_hue,
            neutral_hue=neutral_hue,
            spacing_size=spacing_size,
            radius_size=radius_size,
            text_size=text_size,
            font=font,
            font_mono=font_mono,
        )
        super().set(
            body_background_fill="repeating-linear-gradient(45deg, *primary_200, *primary_200 10px, *primary_50 10px, *primary_50 20px)",
            body_background_fill_dark="repeating-linear-gradient(45deg, *primary_800, *primary_800 10px, *primary_900 10px, *primary_900 20px)",
            button_primary_background_fill="linear-gradient(90deg, *primary_300, *secondary_400)",
            button_primary_background_fill_hover="linear-gradient(90deg, *primary_200, *secondary_300)",
            button_primary_text_color="white",
            button_primary_background_fill_dark="linear-gradient(90deg, *primary_600, *secondary_800)",
            slider_color="*secondary_300",
            slider_color_dark="*secondary_600",
            block_title_text_weight="600",
            block_border_width="3px",
            block_shadow="*shadow_drop_lg",
            button_primary_shadow="*shadow_drop_lg",
            button_large_padding="32px",
        )

seafoam = Seafoam()

with gr.Blocks(theme=seafoam) as demo:
    textbox = gr.Textbox(label="Name")
    slider = gr.Slider(label="Count", minimum=0, maximum=100, step=1)
    with gr.Row():
        button = gr.Button("Submit", variant="primary")
        clear = gr.Button("Clear")
    output = gr.Textbox(label="Output")

    def repeat(name, count):
        time.sleep(3)
        return name * count

    button.click(repeat, [textbox, slider], output)

demo.launch()

看看我们的主题现在看起来多么有趣!只需几个变量的改变,我们的主题看起来就完全不同了。

您可能会发现探索其他预建主题的源代码以了解它们如何修改基础主题是有帮助的。您还可以发现浏览器的检查器在选择UI元素并查看样式面板中使用的CSS变量时非常有用。

分享主题

一旦你创建了一个主题,你可以将其上传到HuggingFace Hub,让其他人查看、使用并在此基础上进行构建!

上传主题

有两种上传主题的方式,通过主题类实例或命令行。我们将使用之前创建的seafoam主题来介绍这两种方法。

  • 通过类实例

每个主题实例都有一个名为push_to_hub的方法,我们可以使用它来将主题上传到HuggingFace hub。

seafoam.push_to_hub(repo_name="seafoam",
                    version="0.0.1",
					hf_token="<token>")
  • 通过命令行

首先将主题保存到磁盘

seafoam.dump(filename="seafoam.json")

然后使用upload_theme命令:

upload_theme\
"seafoam.json"\
"seafoam"\
--version "0.0.1"\
--hf_token "<token>"

为了上传主题,您必须拥有一个HuggingFace账户,并将您的访问令牌作为hf_token参数传递。但是,如果您通过HuggingFace命令行(随gradio一起安装)登录,则可以省略hf_token参数。

version 参数允许您为您的主题指定一个有效的 语义版本 字符串。这样,您的用户能够指定他们希望在其应用程序中使用的主题版本。这也让您可以发布主题更新,而不用担心改变之前创建的应用程序的外观。version 参数是可选的。如果省略,将自动应用下一个补丁版本。

主题预览

通过调用push_to_hubupload_theme,主题资源将被存储在HuggingFace space中。

我们的海泡主题预览在这里:seafoam preview

发现主题

主题画廊展示了所有公开的gradio主题。发布你的主题后,几分钟后它会自动出现在主题画廊中。

你可以根据空间上的点赞数量对主题进行排序,也可以从最近创建到最早创建进行排序,还可以在浅色和深色模式之间切换主题。

下载

要使用中心中的主题,请在ThemeClass上使用from_hub方法并将其传递给您的应用程序:

my_theme = gr.Theme.from_hub("gradio/seafoam")

with gr.Blocks(theme=my_theme) as demo:
    ....

你也可以直接将主题字符串传递给 BlocksInterface (gr.Blocks(theme="gradio/seafoam"))

您可以通过使用语义版本控制表达式将您的应用程序固定到上游主题版本。

例如,以下内容将确保我们从seafoam仓库加载的主题版本在0.0.10.1.0之间:

with gr.Blocks(theme="gradio/seafoam@>=0.0.1,<0.1.0") as demo:
    ....

享受创建你自己的主题吧!如果你制作了一个让你自豪的主题,请通过上传到中心与世界分享! 如果你在Twitter上标记我们,我们可以为你的主题大声宣传!