Skip to main content
The HTML component is for advanced users only. Improper use can lead to serious security vulnerabilities, particularly cross-site scripting (XSS) attacks. Only use this component if you understand the security implications.
The HTML component allows you to include raw HTML in your SQLPage output. Use this for complex layouts, custom styling, or integrating external content that standard components don’t support.

Basic Usage

Include a simple HTML snippet:
SELECT 'html' AS component,
    '<h1 class="text-blue">This text is safe because it is <mark>hardcoded</mark>!</h1>' AS html;

Multiple HTML Snippets

Combine multiple HTML fragments:
SELECT 'html' AS component,
    '<div class="d-flex gap-3 mb-4" style="height: 40px">' AS html;

SELECT '<div class="progress h-100"><div class="progress-bar progress-bar-striped progress-bar-animated" style="width: 10%">10%</div></div>' AS html;

SELECT '<div class="progress h-100"><div class="progress-bar progress-bar-striped progress-bar-animated bg-danger" style="width: 80%">80%</div></div>' AS html;

SELECT '</div>' AS html;

Safe User Content with text

When including user-generated content, use the text parameter to automatically escape HTML:
SELECT 'html' AS component;

SELECT 
    '<p>The following will be sanitized: <mark>' AS html,
    '<script>alert("Failed XSS attack!")</script>' AS text,
    '</mark>. Phew! That was close!</p>' AS post_html;
The text parameter content is displayed as plain text - HTML tags are escaped and shown literally.

Security: The Golden Rule

NEVER include user-provided data in the html parameter. Always use text for user content.

Unsafe (Vulnerable to XSS)

-- DANGEROUS! Never do this!
SELECT 'html' AS component,
    '<div>' || :user_input || '</div>' AS html;
An attacker could enter <script>steal_cookies()</script> as input.

Safe

-- Safe: user input is escaped
SELECT 'html' AS component,
    '<div>' AS html,
    :user_input AS text,
    '</div>' AS post_html;

Custom Components

Create custom Bootstrap components:
SELECT 'html' AS component,
    '
    <div class="alert alert-info alert-dismissible" role="alert">
        <div class="d-flex">
            <div>
                <svg xmlns="http://www.w3.org/2000/svg" class="icon alert-icon" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round">
                    <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
                    <circle cx="12" cy="12" r="9"></circle>
                    <line x1="12" y1="8" x2="12.01" y2="8"></line>
                    <polyline points="11 12 12 12 12 16 13 16"></polyline>
                </svg>
            </div>
            <div>
                <h4 class="alert-title">Custom Alert</h4>
                <div class="text-muted">This is a custom styled alert.</div>
            </div>
        </div>
        <button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    </div>
    ' AS html;

Embedding Visualizations

Include interactive charts from external libraries:
SELECT 'html' AS component,
    '<div id="chart"></div>
    <script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
    <script>
        Plotly.newPlot("chart", [{
            x: [1, 2, 3, 4],
            y: [10, 15, 13, 17],
            type: "scatter"
        }]);
    </script>' AS html;

Custom Forms

Build complex form layouts:
SELECT 'html' AS component,
    '
    <form method="POST" action="process.sql" class="card">
        <div class="card-body">
            <div class="row">
                <div class="col-md-6">
                    <label class="form-label">First Name</label>
                    <input type="text" name="first_name" class="form-control" required>
                </div>
                <div class="col-md-6">
                    <label class="form-label">Last Name</label>
                    <input type="text" name="last_name" class="form-control" required>
                </div>
            </div>
            <button type="submit" class="btn btn-primary mt-3">Submit</button>
        </div>
    </form>
    ' AS html;

Custom CSS

Add page-specific styles:
SELECT 'html' AS component,
    '<style>
        .custom-card {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 2rem;
            border-radius: 1rem;
            box-shadow: 0 10px 30px rgba(0,0,0,0.2);
        }
    </style>' AS html;

SELECT 'html' AS component,
    '<div class="custom-card">
        <h2>Beautiful Custom Card</h2>
        <p>With gradient background and shadow</p>
    </div>' AS html;

Database-Driven HTML

Generate HTML from database content (safely):
SELECT 'html' AS component,
    '<div class="row">' AS html;

SELECT 
    '<div class="col-md-4"><div class="card"><div class="card-body"><h3>' AS html,
    product_name AS text,
    '</h3><p class="text-muted">' AS post_html,
    product_description AS text,
    '</p></div></div></div>' AS post_html
FROM products
WHERE category = 'featured';

SELECT '</div>' AS html;

JavaScript Integration

Add interactivity:
SELECT 'html' AS component,
    '
    <button id="clickMe" class="btn btn-primary">Click Me</button>
    <p id="result"></p>
    <script>
        document.getElementById("clickMe").addEventListener("click", function() {
            document.getElementById("result").innerText = "Button clicked!";
        });
    </script>
    ' AS html;

Responsive Layouts

Create custom responsive grids:
SELECT 'html' AS component,
    '
    <div class="row g-4">
        <div class="col-12 col-md-6 col-lg-4">
            <div class="card h-100">
                <div class="card-body">Card 1</div>
            </div>
        </div>
        <div class="col-12 col-md-6 col-lg-4">
            <div class="card h-100">
                <div class="card-body">Card 2</div>
            </div>
        </div>
        <div class="col-12 col-md-6 col-lg-4">
            <div class="card h-100">
                <div class="card-body">Card 3</div>
            </div>
        </div>
    </div>
    ' AS html;

Top-level Parameters

html
string
Raw HTML content to include in the page. Not sanitized or escaped. Never include untrusted user data here.

Row-level Parameters

html
string
Raw HTML content for this row. Not sanitized or escaped.
text
string
Text content that will be automatically escaped. Use this for user-generated content. HTML tags will be displayed as text, not rendered.
post_html
string
Raw HTML content to include after the text content. Not sanitized or escaped.

Security Best Practices

Content Security Policy

If using inline scripts, configure your Content Security Policy:
SELECT 'http_header' AS component,
    'Content-Security-Policy' AS name,
    'script-src ''self'' ''unsafe-inline'' https://cdn.plot.ly' AS value;

Input Validation

If you must use user input in HTML (not recommended), validate strictly:
-- Only allow alphanumeric characters
SELECT 'html' AS component,
    '<div id="' || REGEXP_REPLACE(:user_id, '[^a-zA-Z0-9]', '') || '">Content</div>' AS html
WHERE :user_id REGEXP '^[a-zA-Z0-9]+$';

Sanitization Libraries

For user HTML (like blog posts), sanitize on input using application logic, not in SQLPage.

When to Use HTML Component

Use the HTML component when:
  • Integrating third-party JavaScript libraries
  • Creating highly custom layouts not possible with standard components
  • Adding custom CSS for specific pages
  • Embedding external content (videos, maps, widgets)
Don’t use it when:
  • Standard SQLPage components can do the job
  • Working with user-generated content (use text or markdown components)
  • You’re unsure about XSS implications

Alternative: Custom Components

For frequently used custom HTML, consider creating reusable custom components. See the custom components documentation for building your own Handlebars templates.

Build docs developers (and LLMs) love