htmx icon indicating copy to clipboard operation
htmx copied to clipboard

The title tags in the body only work when the title tags in the head don't exist

Open kswope opened this issue 1 month ago • 3 comments

You'd expect overriding the default title for some pages would be the expected behavior.

use case: Having a default website title and overriding it only in individual product pages.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/htmx.min.js"></script>
    <title>Document</title><!-- remove for title in body to work -->
  </head>
  <body>
    <title>Document:homepage</title><!-- noop when title in head exists -->
    <h1>hello</h1>
  </body>
</html>

kswope avatar Nov 19 '25 23:11 kswope

Yeah title tags in body are designed as a fallback to allow users to return a partial or body only response and still have the option to override the title and not as a solution to override the specified head title sorry. It should be possible to customize or remove the head data per route on your backend

MichaelWest22 avatar Nov 20 '25 12:11 MichaelWest22

In my app (not the above sample code) I tried to cheat a little and replace the links with

hx-get='/a/b/c' hx-target="main" hx-select="main"

to avoid loading head, and although I verified I'm getting nothing but XHR traffic, I'm still seeing the same behavior.

Are you saying its expected behavior to not be able to override the head-title even if you use hx-select to avoid the head-title, but you have to use a pure partial to override the head-title?

kswope avatar Nov 20 '25 21:11 kswope

I'm sure I copied it from somewhere, but we have a listener that updates the title:

document.addEventListener('forceTitle', function (evt: CustomEvent<any>) {
    if (evt.detail.value) {
        const titleElt = document.querySelector('title');
        if (titleElt) {
            titleElt.innerHTML = evt.detail.value;
        } else {
            window.document.title = evt.detail.value;
        }
    }
});

Then, in our code-behind (C#), we use the htmx trigger header

Response.Htmx(res =>
{
    res.PushUrl(newUrl);
    res.WithTrigger("forceTitle", $"{Title} - SoftwareName");
});

Easily lets us change the page title to whatever we'd like as partials are being passed back and forth.

jr115173 avatar Nov 21 '25 17:11 jr115173