Skip to main content
Blocks is Gradio’s low-level API that gives you complete control over your application’s layout, events, and data flow. While Interface is great for simple demos, Blocks allows you to create sophisticated multi-page applications with custom interactions.

What is Blocks?

Blocks provides more flexibility than Interface by allowing you to:
  1. Control layout - Arrange components exactly how you want using rows, columns, tabs, and accordions
  2. Define custom events - Trigger functions based on any component interaction (clicks, changes, submissions)
  3. Create data flows - Chain events together so outputs from one function become inputs to another
  4. Build multi-page apps - Group related demos with tabs or separate pages

Basic structure

Blocks uses a context manager (the with statement) to define your application:
import gradio as gr

def welcome(name):
    return f"Welcome to Gradio, {name}!"

with gr.Blocks() as demo:
    gr.Markdown("# Hello World!")
    inp = gr.Textbox(placeholder="What is your name?")
    out = gr.Textbox()
    inp.change(welcome, inp, out)

demo.launch()
Key points:
  • Components defined inside the with block are automatically added to the interface
  • Events are set up using component methods like .change(), .click(), etc.
  • You define the function (welcome), inputs (inp), and outputs (out) for each event

Layout components

Rows and Columns

Organize components horizontally and vertically:
import gradio as gr

with gr.Blocks() as demo:
    with gr.Row():
        inp = gr.Textbox(placeholder="Input")
        out = gr.Textbox(placeholder="Output")
    
    with gr.Row():
        submit_btn = gr.Button("Submit")
        clear_btn = gr.ClearButton([inp, out])

Tabs

Create tabbed interfaces for multiple workflows:
import gradio as gr

with gr.Blocks() as demo:
    with gr.Tabs():
        with gr.Tab("Text"):
            text_input = gr.Textbox()
            text_output = gr.Textbox()
        
        with gr.Tab("Image"):
            image_input = gr.Image()
            image_output = gr.Image()

Accordions

Hide advanced options in collapsible sections:
import gradio as gr

with gr.Blocks() as demo:
    prompt = gr.Textbox(label="Prompt")
    
    with gr.Accordion("Advanced Settings", open=False):
        temperature = gr.Slider(0, 2, label="Temperature")
        max_tokens = gr.Slider(1, 2048, label="Max Tokens")

Event listeners

Blocks allows you to attach event listeners to components to trigger functions:

Click events

import gradio as gr

def process(text):
    return text.upper()

with gr.Blocks() as demo:
    inp = gr.Textbox()
    out = gr.Textbox()
    btn = gr.Button("Process")
    
    btn.click(fn=process, inputs=inp, outputs=out)

Change events

Trigger when a component’s value changes:
with gr.Blocks() as demo:
    inp = gr.Textbox()
    out = gr.Textbox()
    
    inp.change(fn=lambda x: x.upper(), inputs=inp, outputs=out)

Submit events

Trigger when the user presses Enter in a textbox:
with gr.Blocks() as demo:
    inp = gr.Textbox()
    out = gr.Textbox()
    
    inp.submit(fn=process, inputs=inp, outputs=out)

Chaining events

One of Blocks’ most powerful features is event chaining with .then(), .success(), and .failure():
import gradio as gr

def step1(text):
    return text.upper()

def step2(text):
    return text + "!!!"

def cleanup():
    return "Processing complete"

with gr.Blocks() as demo:
    inp = gr.Textbox()
    mid = gr.Textbox()
    out = gr.Textbox()
    status = gr.Textbox()
    btn = gr.Button("Run")
    
    btn.click(step1, inp, mid).then(
        step2, mid, out
    ).success(
        cleanup, None, status
    )
.then() runs after the previous event completes (regardless of success/failure), .success() runs only on success, and .failure() runs only on errors.

Multiple inputs and outputs

Pass lists of components for functions that need multiple inputs or produce multiple outputs:
import gradio as gr

def calculate(x, y, operation):
    if operation == "add":
        return x + y, f"Added {x} and {y}"
    elif operation == "multiply":
        return x * y, f"Multiplied {x} and {y}"

with gr.Blocks() as demo:
    with gr.Row():
        num1 = gr.Number(label="First Number")
        num2 = gr.Number(label="Second Number")
        op = gr.Dropdown(["add", "multiply"], label="Operation")
    
    result = gr.Number(label="Result")
    description = gr.Textbox(label="Description")
    btn = gr.Button("Calculate")
    
    btn.click(
        fn=calculate,
        inputs=[num1, num2, op],
        outputs=[result, description]
    )

State management

Use the State component to maintain values between interactions:
import gradio as gr

def increment(count):
    count = count + 1 if count else 1
    return count, f"Count: {count}"

with gr.Blocks() as demo:
    state = gr.State(value=0)
    output = gr.Textbox(label="Counter")
    btn = gr.Button("Increment")
    
    btn.click(
        fn=increment,
        inputs=state,
        outputs=[state, output]
    )
State components are not visible in the UI but persist values across function calls for each user session.

Queue and concurrency

Enable queueing to handle multiple users and long-running functions:
import gradio as gr
import time

def slow_function(text):
    time.sleep(3)
    return text.upper()

with gr.Blocks() as demo:
    inp = gr.Textbox()
    out = gr.Textbox()
    btn = gr.Button("Process")
    
    btn.click(
        fn=slow_function,
        inputs=inp,
        outputs=out,
        concurrency_limit=3  # Allow up to 3 simultaneous requests
    )

demo.queue()  # Enable the queue
demo.launch()

Rendering dynamically

Components render as soon as they’re created within a Blocks context. Set render=False to prevent automatic rendering:
import gradio as gr

with gr.Blocks() as demo:
    # This renders immediately
    visible_box = gr.Textbox()
    
    # This doesn't render yet
    hidden_box = gr.Textbox(render=False)
    
    # Render it later somewhere else
    with gr.Column():
        hidden_box.render()

Advanced features

Custom JavaScript

Run JavaScript code before or after Python functions:
with gr.Blocks() as demo:
    inp = gr.Textbox()
    out = gr.Textbox()
    btn = gr.Button()
    
    btn.click(
        fn=lambda x: x.upper(),
        inputs=inp,
        outputs=out,
        js="() => alert('Processing started!')"
    )

Load events

Run functions when the page loads:
def initialize():
    return "Welcome! App loaded at " + str(time.time())

with gr.Blocks() as demo:
    output = gr.Textbox()
    
    demo.load(fn=initialize, inputs=None, outputs=output)

Cancelling events

Cancel running events when a new event starts:
with gr.Blocks() as demo:
    inp = gr.Textbox()
    out = gr.Textbox()
    start_btn = gr.Button("Start")
    stop_btn = gr.Button("Stop")
    
    click_event = start_btn.click(slow_function, inp, out)
    stop_btn.click(None, None, None, cancels=[click_event])

Configuration

Blocks supports various configuration options:
with gr.Blocks(
    title="My App",
    analytics_enabled=True,
    fill_height=True,
    fill_width=False,
    delete_cache=(86400, 86400)  # Delete temp files daily
) as demo:
    # Your components here
    pass

When to use Blocks

Use Blocks when you need:
  • Custom layouts beyond simple input/output
  • Multiple related functions in one interface
  • Complex event chains and data flows
  • Multi-page or tabbed applications
  • Advanced state management
For simple function wrapping, consider using Interface instead.

See also