Vix.cpp v2.7.0 is here Read the blog
Skip to content

HTML helpers

Vix UI provides small HTML helpers for building safe HTML fragments from C++.

Use them when you need to generate a piece of HTML without writing a full template.

They are useful for:

txt
small components
server-rendered fragments
HTML attributes
safe text escaping
dynamic tags
layout helpers
forms and UI primitives

For full pages, prefer templates and vix::ui::View.

Basic example

cpp
#include <vix/ui/html/Html.hpp>
#include <vix/ui/html/HtmlAttrs.hpp>

vix::ui::HtmlAttrs attrs;

attrs.set("class", "card");
attrs.set("id", "welcome");

const std::string html =
    vix::ui::Html::tag(
        "section",
        vix::ui::Html::tag("h1", vix::ui::Html::text("Vix UI")) +
            vix::ui::Html::tag(
                "p",
                vix::ui::Html::text("Small HTML fragments from C++.")),
        attrs);

Output:

html
<section class="card" id="welcome">
  <h1>Vix UI</h1>
  <p>Small HTML fragments from C++.</p>
</section>

Escaped text

Use Html::text() when the value comes from a user, a request, a database, or any untrusted source.

cpp
const std::string username = "<script>alert(1)</script>";

const std::string html =
    vix::ui::Html::tag(
        "p",
        vix::ui::Html::text(username));

Output:

html
<p>&lt;script&gt;alert(1)&lt;/script&gt;</p>

This prevents unsafe HTML from being rendered directly.

Raw HTML

Use Html::raw() only when the HTML is trusted and already generated by your application.

cpp
const std::string html =
    vix::ui::Html::tag(
        "div",
        vix::ui::Html::raw("<strong>Ready</strong>"));

Output:

html
<div><strong>Ready</strong></div>

Do not pass user input to Html::raw().

Attributes

HtmlAttrs stores and renders HTML attributes.

cpp
vix::ui::HtmlAttrs attrs;

attrs.set("class", "button");
attrs.set("id", "save-button");
attrs.set("data-action", "save");

const std::string html =
    vix::ui::Html::tag(
        "button",
        vix::ui::Html::text("Save"),
        attrs);

Output:

html
<button class="button" data-action="save" id="save-button">Save</button>

Attribute values are escaped automatically.

cpp
vix::ui::HtmlAttrs attrs;

attrs.set("title", R"(Save "draft" & continue)");

Output:

html
title="Save &quot;draft&quot; &amp; continue"

Boolean attributes

Use boolean attributes for HTML attributes that do not need a value.

cpp
vix::ui::HtmlAttrs attrs;

attrs.boolean("disabled", true);
attrs.boolean("hidden", false);

Only enabled boolean attributes are rendered.

html
disabled

You can also remove a boolean attribute by setting it to false.

cpp
attrs.boolean("disabled", false);

Conditional attributes

Use set_if() when an attribute should only appear in some cases.

cpp
const bool active = true;

vix::ui::HtmlAttrs attrs;

attrs.set("class", "nav-link");
attrs.set_if(active, "aria-current", "page");

Output:

html
class="nav-link" aria-current="page"

Open and close tags

Use open_tag() and close_tag() when you need to build HTML in multiple steps.

cpp
vix::ui::HtmlAttrs attrs;

attrs.set("class", "container");

std::string html;

html += vix::ui::Html::open_tag("main", attrs);
html += vix::ui::Html::tag("h1", vix::ui::Html::text("Dashboard"));
html += vix::ui::Html::close_tag("main");

Output:

html
<main class="container"><h1>Dashboard</h1></main>

Normal tags

Use Html::tag() for tags with opening and closing elements.

cpp
const std::string title =
    vix::ui::Html::tag(
        "h1",
        vix::ui::Html::text("Hello Vix"));

Output:

html
<h1>Hello Vix</h1>

With attributes:

cpp
vix::ui::HtmlAttrs attrs;

attrs.set("class", "title");

const std::string title =
    vix::ui::Html::tag(
        "h1",
        vix::ui::Html::text("Hello Vix"),
        attrs);

Output:

html
<h1 class="title">Hello Vix</h1>

Void tags

Use Html::void_tag() for tags that do not have closing tags.

cpp
vix::ui::HtmlAttrs attrs;

attrs.set("charset", "utf-8");

const std::string meta =
    vix::ui::Html::void_tag("meta", attrs);

Output:

html
<meta charset="utf-8" />

Common void tags include:

txt
meta
link
img
input
br
hr

Doctype

Use Html::doctype() when generating a full HTML document.

cpp
const std::string html =
    vix::ui::Html::doctype() +
    "<html lang=\"en\">"
    "<head>"
    "<meta charset=\"utf-8\">"
    "<title>Vix UI</title>"
    "</head>"
    "<body>"
    "<h1>Hello</h1>"
    "</body>"
    "</html>";

Output starts with:

html
<!doctype html>

Practical card example

cpp
#include <vix/core.hpp>
#include <vix/ui.hpp>

int main()
{
  vix::App app;

  app.get("/", [](vix::Request &req, vix::Response &res) {
    (void)req;

    vix::ui::HtmlAttrs card_attrs;
    card_attrs.set("class", "card");

    vix::ui::HtmlAttrs title_attrs;
    title_attrs.set("class", "title");

    const std::string card =
        vix::ui::Html::tag(
            "section",
            vix::ui::Html::tag(
                "h1",
                vix::ui::Html::text("Vix UI HTML"),
                title_attrs) +
                vix::ui::Html::tag(
                    "p",
                    vix::ui::Html::text(
                        "Small HTML fragments generated safely from C++.")),
            card_attrs);

    const std::string html =
        vix::ui::Html::doctype() +
        "<html lang=\"en\">"
        "<head>"
        "<meta charset=\"utf-8\">"
        "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">"
        "<title>Vix UI HTML</title>"
        "</head>"
        "<body><main>" +
        card +
        "</main></body></html>";

    res.ui(vix::ui::HtmlResponse::html(html));
  });

  app.run(8080);
  return 0;
}

Valid names

Tag names and attribute names are validated.

Valid examples:

txt
div
section
custom-element
svg:path
class
data-id
aria-label
_private

Invalid examples:

txt
1div
bad name
bad/name

Invalid names throw a HtmlError.

cpp
try
{
  const std::string html =
      vix::ui::Html::tag("1bad", "content");
}
catch (const vix::ui::HtmlError &)
{
  // invalid tag name
}

Common mistakes

Passing user input as raw HTML

Wrong:

cpp
std::string html = vix::ui::Html::raw(user_input);

Correct:

cpp
std::string html = vix::ui::Html::text(user_input);

Building full pages only with C++ strings

HTML helpers are good for small fragments.

For full pages, prefer:

cpp
vix::ui::View("dashboard.html")

Templates are easier to read and maintain.

Forgetting attributes are escaped

You do not need to escape attribute values manually.

cpp
attrs.set("title", R"(Hello "Vix" & C++)");

Vix UI handles the escaping when rendering.

Using HTML helpers as a frontend framework

HTML helpers are not a virtual DOM.

They are small server-side helpers for generating safe HTML.

For pages, use templates.

For small components, use Html, HtmlAttrs, and HtmlEscape.

Next step

Continue with HTML responses.

Open the HTML response guide

Released under the MIT License.