On this page, you'll find documentation, tutorials, and tips on how to change the UI in Gradio on Hugging Face. While editing the UI can be fun and engaging, remember that the primary focus of your final project should be the chatbot itself.
Interfaces & Blocks
Gradio provides four main tools—ChatInterface, Interface, InterfaceBlocks, and TabbedInterface—for building interactive demos:
- ChatInterface specializes in chatbot applications, automatically managing message history and formatting.
- Interface is the most beginner-friendly option, perfect for quickly turning a function into a simple app with inputs and outputs.
- When you want to organize multiple Interfaces or Blocks into a single app with tabbed navigation, TabbedInterface lets you display each one in its own tab for a cleaner, modular experience.
- For more complex apps with custom layouts and logic, Blocks offers full control over every component and interaction.
Open each of the toggles below to get more information and see an example code snippet for each tool.
ChatInterface
ChatInterface is Gradio's specialized tool for creating chatbot applications, which you've already used in your previous project! It's designed specifically for chat-style interactions where users send messages and receive responses, automatically handling the chat history and message display.
import gradio as gr def echo(message, history): return message echo_chatbot = gr.ChatInterface(echo) echo_chatbot.launch()
ChatInterface only needs one main parameter: a function that takes the user's message and chat history and returns the chatbot's response. This is exactly what you did when you created your
respond function that processed messages and used the HuggingFace model to generate replies!Interface
Interface is Gradio's beginner-friendly tool for quickly turning your Python functions into interactive web apps. To use Interface, you only need to tell it three things: what function you want to make interactive, what kind of input boxes or buttons users should see (like text boxes or file uploads), and how you want the results displayed (like text).
import gradio as gr def greet(name, intensity): return "Hello, " + name + "!" * intensity greeting = gr.Interface( fn=greet, inputs=["text", gr.Slider(value=2, minimum=1, maximum=10, step=1)], outputs=[gr.Textbox(label="greeting", lines=3)] ) greeting.launch()
This example shows how to use those three parameters within the Interface: fn, inputs, and outputs.
fn=greet: Thegreetfunction defines what happens when the user clicks the Submit button. It takes the input values, processes them, and returns the result to be displayed in the output component.
inputs: There are two inputs defined in this example."text": A text box for the name (”text”a shortcut forgr.Textbox())gr.Slider(...): A slider to choose the intensity (how many exclamation marks)
outputs: Specifies that the result should be shown in agr.Textbox()labeled "greeting" that displays the value returned by the function.
Interface is part of a family of high-level Gradio tools that includes ChatInterface (which you used in your previous chatbot project). While ChatInterface is specifically designed for chat applications with message history, Interface works for any type of function that takes inputs and produces outputs.
TabbedInterface
TabbedInterface is Gradio's tool for combining multiple components into a single, tabbed experience. To use TabbedInterface, you simply pass in a list of existing Interface or Blocks objects, and each one will appear in its own tab.
import gradio as gr def greet(name, intensity): return "Hello, " + name + "!" * intensity def echo(message, history): return message greeting = gr.Interface( fn=greet, inputs=["text", gr.Slider(value=2, minimum=1, maximum=10, step=1)], outputs=[gr.Textbox(label="greeting", lines=3)]) echo_chatbot = gr.ChatInterface(echo) demo = gr.TabbedInterface([greeting, echo_chatbot], ["Greeting", "Chat"]) demo.launch()
This code creates a simple Gradio app with two tabs to combine the previous two examples into a single user interface. The "Greeting" tab lets users enter a name and choose an intensity level to generate a custom greeting using the greet function. The "Chat" tab opens a basic chatbot that echoes back whatever the user types.
Only the visible components inside each app are shown in the tab, so the experience stays clean and focused. While it's great for modular organization, keep in mind that some advanced customizations from Blocks (like custom CSS or JavaScript) may no carry over into individual tabs.
Blocks
Blocks is Gradio's flexible layout system that lets you arrange components more precisely than the default Interface or ChatInterface. With Blocks, you can decide where each button, text box, and output area goes on the page and control what happens when users click different buttons. To use Blocks, you create a Blocks object, use Python's "with" statement to work inside it and then arrange your components.
import gradio as gr def echo(message, history): return message about_text = """ ## About this bot This demo **simply echoes** everything you type. Use the chat box on the right to try it out! """ with gr.Blocks() as demo: with gr.Row(): with gr.Column(scale=1): gr.Markdown(about_text) with gr.Column(scale=2): gr.ChatInterface(echo) demo.launch()
Inside the Blocks object, we used
gr.Row() to place components side-by-side in a horizontal line. Within that row, we added two gr.Column() components: the first has scale=1 (taking up about a third of the space) and shows the "About" text, while the second has scale=2 (taking up about two-thirds) and contains the chatbot.As you can see,
gr.Blocks gives you full control over the layout of your Gradio app, allowing you to arrange components in rows, columns, or custom groupings. It’s ideal when you want to include more components like images, headers, or multiple sections. Blocks also support combining different interfaces in one app. This flexibility makes it great for building more complex demos.When you’re building your capstone projects, keep these tools in mind to help you build the user interface that matches your needs. Interface and ChatInterface make it easy to get started, while Blocks and TabbedInterface give you the flexibility to scale and organize more complex projects. As you grow more comfortable with Gradio, you can mix and match these tools to create powerful, user-friendly projects using only Python!
Images
You can easily add images to your Gradio user interface by using the Blocks layout!
with gr.Blocks() as chatbot: gr.Image( value="orange-banner.png", show_label=False, show_share_button = False, show_download_button = False) gr.ChatInterface(respond, type="messages")
Step 1: Find an image and add it to the files of your project or save the URL. Check out the screenshot below to see how to upload a new file!
Â
Step 2: Wrap the ChatInterface in a Gradio Blocks layout to add the image above the ChatInterface with gr.Image().
The first parameter,
value, accepts the image address as a string. You can upload an image to your files and use the image name, or you can take a URL and paste it. We recommend the first option so that the image lives permanently in your files (as URLs could become outdated).with gr.Blocks() as chatbot: gr.Image(value="orange-banner.png") gr.ChatInterface(respond, type="messages")
Step 3: Et voila! You’ll have an image above your chatbot.
The
show_label, show_share_button and show_download_button parameters are set to False in this example, so that these buttons don’t appear in the corner of your image in the interface.Step 4: You can further customize the image with additional parameters.
Other optional parameters for resizing the image:
scalespecifies the relative size of the image compared to adjacent components. This value must be an integer!
- Alternatively, you can also use the
heightandwidthparameters to adjust the pixels (e.g.width = 500).
Themes
Gradio themes are a powerful way to customize the visual appearance of your applications. Think of themes as different visual styles that change how your app looks. You can choose from a variety of themes, or create your own. Themes control hundreds of visual elements including colors, fonts, spacing, borders, shadows, and animations.
Option 1: Simple Built-In Theme
To apply a built-in theme to your app, simply pass the
theme parameter to your Interface, Blocks, or ChatInterface.# Just add the theme parameter - that's it! chatbot = gr.ChatInterface(respond, type="messages", theme=gr.themes.Soft())
Â
Gradio comes with a set of themes which you can load from
gr.themes. The following are just a few of the built-in themes available. Check out the docs for more!gr.themes.Soft()- shown in the example above, the "soft" theme uses a purple primary color and white secondary color. It also increases the border radius around buttons and form elements and highlights labels.
gr.themes.Citrus()- the "citrus" theme uses a yellow primary color, highlights form elements that are in focus, and includes fun 3D effects when buttons are clicked.
gr.themes.Monochrome()- the "monochrome" theme uses a black primary and white secondary color, and uses serif-style fonts, giving the appearance of a black-and-white newspaper.
Option 2: Quick Color Customization
Although each theme has hundreds of CSS variables, the values for most of them are controlled by 8 core variables that you can adjust by modifying the value for each variable in the parentheses after the name of the theme.
# Customize colors, sizing and fonts custom_theme = gr.themes.Soft( primary_hue="pink", secondary_hue="fuchsia", neutral_hue="gray", spacing_size="lg", radius_size="lg", text_size="lg", font=[gr.themes.GoogleFont("IBM Plex Sans"), "sans-serif"], font_mono=[gr.themes.GoogleFont("IBM Plex Mono"), "monospace"] ) chatbot = gr.ChatInterface(respond, type="messages", theme=custom_theme) chatbot.launch(ssr_mode=False)
You don’t need to assign all 8 of these core variables to a new value—you can pass in new values for only the variables you want to adjust! For more information about these core variables, check out the docs.
There was a font loading issue because Gradio's default server-side rendering (SSR) mode interferes with external resource loading, including Google Fonts. Setting
ssr_mode=False in the launch() method switches to client-side rendering, allowing the browser to properly load Google Fonts during the rendering process. This trade-off resolves font compatibility issues at the cost of slightly slower initial page loads.Option 3: Advanced Customization with .set()
.set()Use the
.set() method of the theme object to modify the values of CSS variables after the theme has been loaded. The .set() method gives you granular control over individual CSS variables within a theme, allowing you to fine-tune specific visual elements that the core variables don't directly control.chat_theme = gr.themes.Soft( primary_hue="indigo", secondary_hue="purple", neutral_hue="gray", spacing_size="lg", radius_size="lg" ).set( # Input area input_background_fill="*neutral_50", input_border_color_focus="*primary_300", # Button styling button_primary_background_fill="*primary_500", button_primary_background_fill_hover="*primary_400" ) chatbot = gr.ChatInterface(respond, type="messages", theme=chat_theme) chatbot.launch(ssr_mode=False)
This approach is particularly useful when you want to maintain the overall aesthetic of a built-in theme while making targeted adjustments to specific components like chat bubbles, input fields, or buttons.
You can also check out the Gradio Theme Gallery to explore existing themes created by others. With these tools and techniques, you can create beautiful, professional-looking Gradio applications that match your brand or personal style preferences!
Form
You might want to include a form that provides the chatbot with more personalized information about the user. This would allow the chatbot to use that information to inform the response, creating a more personalized and seamless experience. In the example below, the form collects the user’s name and then we use that input to inform the chatbot’s response. While the chatbot in this example isn’t “smart” yet—it simply echoes your input using string formatting—it demonstrates how you can start incorporating user input into your chatbot’s behavior. You might expand this by collecting more information in the form, like a user's preferences, interests, or goals, and using that data to shape the chatbot’s responses. This approach lays the groundwork for more context-aware, conversational AI that feels tailored to the individual user.
import gradio as gr def reply(user_msg: str, history: list, name: str): name = name or "friend" assistant_msg = f"Nice to meet you, {name}! You said: {user_msg}" history = history + [ {"role": "user", "content": user_msg}, {"role": "assistant", "content": assistant_msg}, ] return history, "" # clear the textbox def set_name_and_greet(name: str): name = name or "friend" greeting = [ {"role": "assistant", "content": f"Hi, {name}! How can I help you?"} ] return name, greeting # matches the two outputs with gr.Blocks() as demo: name_state = gr.State("") # remembers the chosen name with gr.Row(): with gr.Column(scale=1): gr.Markdown("### Enter your name, then click **Set Name**") name_input = gr.Textbox(placeholder="Type your name here…") set_btn = gr.Button("Set Name") gr.Markdown("_After the greeting appears, start chatting →_") with gr.Column(scale=2): chatbot = gr.Chatbot(label="Chat", type="messages") user_text = gr.Textbox(placeholder="Ask me something…") set_btn.click( fn=set_name_and_greet, inputs=name_input, outputs=[name_state, chatbot], # update state & chatbot history show_progress=False, ) user_text.submit( fn=reply, inputs=[user_text, chatbot, name_state], # latest msg, history, name outputs=[chatbot, user_text], # update history & clear input ) demo.launch()
This code uses
gr.Blocks to create a custom layout with two columns: one for entering a name in a form and one for chatting. Unlike gr.ChatInterface, which handles input and history for you, this example uses gr.Chatbot for more control, allowing us to manage the text input, name storage, and conversation history manually. The user's name is saved using gr.State, a hidden variable that keeps information between actions. When the user clicks the "Set Name" button, it stores their name and displays a greeting in the chatbot. After that, messages typed into the textbox trigger the reply function, which uses the saved name to personalize responses.In this example, we used Gradio Blocks to build a custom layout that separates the name input area from the chatbot, giving us more control over how users interact with the interface. Instead of using the default ChatInterface, we combined individual components—textboxes, buttons, state, and a chatbot—to manage the conversation flow manually.
While the chatbot responds using simple string formatting and not a large language model, this example shows how you can start incorporating user input (like a name) to make your chatbot feel more interactive. It’s a helpful foundation if you’re looking to build more personalized or intelligent chatbots later!