0017 — CSS do app no kit de UI: link fixo para app.css¶
Status: Aprovado · Responsável: Gustavo Madruga · Atualizado em: 2026-07-17 · Decidido em: 2026-07-17
Contexto¶
A 0015 removeu o headComExtras do kit — com razão:
dois <head> no mesmo documento quebravam toda view, e naquele momento nenhuma view
usava o slot. A saída prescrita foi "escreva o <head> à mão nessa tela e traga o caso ao
central". A 0015 fechou o slot, mas o head(title) linka só o Bootstrap e o
custom-theme.css — e o custom-theme.css é identidade da casa, rastreado, que não se
edita por app. Um app com componentes próprios (timeline, tiles, stepper, badges de domínio)
não tinha onde pôr o CSS deles.
A resposta "escreva o <head> à mão" não escala: num app de 16 telas, escrever o <head> em
todas descarta justamente o fragment que o kit existe para dar.
Não era hipótese — já tinha acontecido em dois apps, com dois contornos diferentes:
int-pied(17 views no kit): fragment localcomponentes :: appCssemitindo o<link>dentro do<body>. HTML5 permite e todo navegador aplica, mas é contorno local de lacuna de template.bi-comercial-xls(7 views): forkou olayout.htmle documentou a divergência num bloco "DIVERGÊNCIAS LOCAIS" no cabeçalho.
O fork é o dado que decide. O layout.html forkado ainda carregava o
<th:block th:fragment="styles"> morto que a 0.21.0 removera do central: fork sai do
radar do /xadm-docs e congela o app numa versão velha do kit — deixa de receber as
correções, inclusive as de bug. E os dois apps escolheram, independentemente, o mesmo
caminho: /css/app.css. A convenção certa foi descoberta duas vezes porque o kit não a
prescrevia — o mesmo padrão da 0016, onde o integrador
inventou a hospedeira sozinho.
Decisão¶
O head(title) do kit sempre linka /css/app.css, depois do custom-theme.css. Todo
app que usa o kit tem public/css/app.css, nem que vazio; a /xadm-docs o scaffolda de
templates/app.css na criação do app.
Dois CSS, dois donos (§1.9):
custom-theme.css |
app.css |
|
|---|---|---|
| O que é | identidade da casa | componentes deste app |
| Dono | o central | o app |
| Rastreado | sim, verbatim | não — scaffold, copiado uma vez |
Descartadas:
- Model attr
${appCss}(th:if="${appCss != null}") — segue o padrão de model attrs que o kit já usa e evita o 404, mas obriga todo controller a setar o attr (ou o app a montar umViewsModelDecorator): complexidade permanente no app para um<link>estático. - Fragment irmão em 2º arquivo (
layout-head.html :: headComCss) — a 0015 verificou que essa cura renderiza; o custo é um 2º rastreado, dois donos do markup do<head>(§1.9) e duas convenções para a mesma coisa. - Normatizar o contorno do
int-pied(<link>no<body>) — funciona, mas deixa cada app reinventando o fragment e o kit sem dono do assunto: é o que produziu os dois contornos divergentes.
Consequências¶
- Nenhum app quebra. As 37 views reais seguem chamando
head('Título')com um parâmetro — o fragment não mudou de assinatura, e não há segundo<head>(a 0015 continua valendo: slot de markup arbitrário no<head>segue não existindo). - Custo aceito: app sem CSS de componente precisa do
app.cssvazio, senão o<link>fixo dá 404 em toda página. O scaffold (só comentário) resolve; é uma cópia, não uma obrigação recorrente. - O scaffold mora em
templates/app.css, achatado, fora detemplates/public/— o que está lá dentro a/xadm-docscopia verbatim, e um scaffold ali seria sobrescrito a cada re-derivação, apagando o CSS do app. Glob não leva exceção; move-se a origem (mesma decisão de 0.23.1, quando ocustom-theme.csssaiu deviews/). app.cssvem por último na cascata, então sobrescrever a identidade "funciona". Isso é convenção, não gate: identidade divergente por app é o problema que o kit existe para resolver, e quem precisa de algo da casa traz o caso ao central (§6).- Migração oportunista: os dois contornos continuam funcionando; ninguém precisa correr.
O
bi-comercial-xlsganha mais em des-forkar (volta a receber correção do kit) do que oint-piedem trocar o fragment local pelo<link>do kit.