Intermediate

Gradio Blocks

gr.Blocks() gives you full control over layout, event handling, and component interactions. Build multi-step workflows, tabbed interfaces, and complex UIs that go beyond what Interface offers.

Basic Blocks Layout

Python
import gradio as gr

with gr.Blocks() as demo:
    gr.Markdown("# My Custom App")

    with gr.Row():
        with gr.Column(scale=2):
            input_text = gr.Textbox(label="Input", lines=5)
            btn = gr.Button("Generate", variant="primary")
        with gr.Column(scale=3):
            output_text = gr.Textbox(label="Output", lines=5)

    btn.click(fn=my_function, inputs=input_text, outputs=output_text)

demo.launch()

Layout Components

gr.Row()

Place components side by side horizontally. Use equal_height=True to align components.

gr.Column()

Stack components vertically. Use scale to control relative widths within a Row.

📂

gr.Tab()

Create tabbed interfaces for organizing different sections of your app.

👁

gr.Accordion()

Collapsible sections for advanced options that users can expand when needed.

Tabbed Interface

Python
with gr.Blocks() as demo:
    with gr.Tabs():
        with gr.Tab("Text Generation"):
            text_input = gr.Textbox(label="Prompt")
            text_output = gr.Textbox(label="Response")
            text_btn = gr.Button("Generate")

        with gr.Tab("Image Analysis"):
            image_input = gr.Image(type="pil")
            image_output = gr.Label()
            image_btn = gr.Button("Classify")

    text_btn.click(generate_text, text_input, text_output)
    image_btn.click(classify_image, image_input, image_output)

Event Handling

Blocks supports multiple event types beyond simple button clicks:

Python
with gr.Blocks() as demo:
    text = gr.Textbox(label="Input")
    output = gr.Textbox(label="Output")
    btn = gr.Button("Submit")

    # Button click
    btn.click(fn=process, inputs=text, outputs=output)

    # Real-time as user types
    text.change(fn=live_preview, inputs=text, outputs=output)

    # On Enter key
    text.submit(fn=process, inputs=text, outputs=output)

    # Chained events
    btn.click(fn=step1, inputs=text, outputs=output) \
       .then(fn=step2, inputs=output, outputs=output)

State Management

Python
with gr.Blocks() as demo:
    # Per-session state (each user gets their own)
    history = gr.State([])

    chatbot = gr.Chatbot()
    msg = gr.Textbox(label="Message")

    def respond(message, chat_history):
        response = generate_response(message)
        chat_history.append((message, response))
        return "", chat_history

    msg.submit(respond, [msg, chatbot], [msg, chatbot])

Theming

Python
# Built-in themes
demo = gr.Blocks(theme=gr.themes.Soft())
demo = gr.Blocks(theme=gr.themes.Monochrome())
demo = gr.Blocks(theme=gr.themes.Glass())

# Custom theme
my_theme = gr.themes.Soft(
    primary_hue="indigo",
    secondary_hue="blue",
    font=[gr.themes.GoogleFont("Inter"), "sans-serif"],
)
demo = gr.Blocks(theme=my_theme)
Blocks vs Interface: Use Interface for quick single-function demos. Use Blocks when you need custom layouts, multiple event handlers, state management, or multi-step workflows.

What's Next?

Now that you can build custom UIs, let's learn how to deploy your Gradio apps — from instant sharing to production deployment on Hugging Face Spaces.