Um design system completo, do zero, sem dependências externas
Cerne é um framework CSS + JS autocontido — sem CDNs, sem jQuery, sem builds obrigatórios em produção. Foi desenhado para servir múltiplos domínios com o mesmo sistema de tokens e componentes: dashboards administrativos, ambientes de aprendizagem, sistemas de gestão, agendamento de salas e blogs.
Uma ferramenta potente para os tempos modernos de desenvolvimento web
O Cerne está na versão 0.1 — um design system inteiro, construído do zero, com um propósito simples: dar a qualquer pessoa uma base rápida, robusta e gratuita para tirar sistemas do papel e colocá-los na internet, sem depender de CDN, sem licença, sem vendor lock-in e sem paywall. Código aberto, acessível a todo mundo, para sempre.
O que já vem pronto na v0.1
- 40+ componentes de produção — app shell, datatable, calendário, gráficos, chat, video player, modais, formulários avançados e muito mais.
- 43 exemplos completos prontos para copiar: dashboards, e-commerce, streaming, webmail, rede social, portal de notícias, LLM chat, smart TV...
- Zero dependências externas — sem jQuery, sem CDN, sem build obrigatório em produção. Abre com um duplo clique no HTML.
- Dark mode nativo e
prefers-reduced-motion/prefers-color-schemerespeitados automaticamente.
- RTL de verdade via propriedades lógicas — não é um hack de espelhamento.
- Acessibilidade WCAG 2.1 AA por padrão em todo componente interativo.
- Internacionalização real — 168 páginas de exemplo traduzidas em CJK, árabe, hindi e russo, não só a interface.
- CSS moderno de verdade — container queries, cascade layers,
color-mix(),clamp(), densidade configurável pordata-density.
É uma v0.1 por escolha, não por limitação: o núcleo já está sólido e em uso real nos 43 exemplos acima, mas o projeto segue evoluindo em público — cada versão nova adiciona mais primitivos, mais idiomas, mais componentes, sem quebrar o que já existe.
Criador e mantenedor do Cerne. Todo o framework — tokens, componentes, os 43 exemplos e as variantes regionais — foi desenhado por Ricardo e construído em colaboração com IA (Claude, da Anthropic), com o objetivo de deixar uma ferramenta boa, aberta e gratuita para quem está construindo a próxima geração de sistemas na web.
Instalação
Copie os arquivos compilados de dist/ para o seu projeto e referencie-os diretamente. Nenhuma etapa de build é necessária para consumir o framework.
<link rel="stylesheet" href="dist/css/cerne.css">
<!-- No fim do body: script clássico (não type="module") para expor window.Cerne -->
<script src="dist/js/cerne.js"></script>
Para evitar o "flash" do tema errado antes do JS carregar, inclua este trecho no
<head>, antes do CSS:
<script>
var t = localStorage.getItem('cerne-theme');
if (t) document.documentElement.setAttribute('data-theme', t);
</script>
Cores
Paletas primitivas de 11 tons + camada semântica (--cerne-color-primary,
-hover, -active, -subtle...) que troca de
valor automaticamente entre os temas claro e escuro. Os valores abaixo são
lidos ao vivo do CSS compilado — nunca ficam dessincronizados desta documentação.
Espaçamento
Escala de 4px, exposta como --cerne-space-* e como utilitários p-*, m-*, gap-*.
Tipografia
Escala modular (~1.25), fonte padrão = stack de sistema (zero requisições de rede). Troque --cerne-font-sans para usar uma fonte própria self-hosted.
Radius & Sombra
Elevação com receitas distintas para claro/escuro — sombras escuras não desaparecem sobre fundo escuro.
Radius
Sombra
Grid
API clássica .row/.col-* sobre CSS Grid, mais utilitários .grid-cols-* / .col-span-* com prefixos responsivos md:, lg:.
<div class="row">
<div class="col-12 col-md-4">...</div>
<div class="col-12 col-md-4">...</div>
<div class="col-12 col-md-4">...</div>
</div>
App Shell
O primitivo central para dashboards: sidebar + topbar + main via grid-template-areas, com colapso para off-canvas abaixo de lg. Esta própria página usa .app-shell.
<div class="app-shell" id="app-shell">
<div class="app-shell__backdrop"></div>
<aside class="app-shell__sidebar">...</aside>
<header class="app-shell__topbar">...</header>
<main class="app-shell__main">...</main>
</div>
Botões
Variantes sólida, contornada e fantasma para cada cor semântica, mais tamanhos e estado de carregamento.
<button class="btn btn-primary">Primário</button>
<button class="btn btn-outline-primary">Contornado</button>
<button class="btn btn-ghost-primary">Fantasma</button>
Formulários
Controles nativos estilizados, validação via data-cerne-validate (Constraint Validation API) e mensagens de erro customizáveis por atributo.
<form data-cerne-validate novalidate>
<div class="form-group">
<label class="form-label" for="email">E-mail</label>
<input class="form-control" type="email" id="email" required
data-error-required="Informe seu e-mail.">
<span class="form-error"></span>
</div>
</form>
Mais formulários
Label flutuante, senha com força e visibilidade, código OTP, busca com limpar, slider, tags, combobox, cards selecionáveis, seletor segmentado, upload por arraste e contador de caracteres — para cobrir qualquer fluxo, de login a checkout.
<mark>.
<div class="form-floating">
<input class="form-control" placeholder=" " id="name">
<label for="name">Nome completo</label>
</div>
<div class="otp-input" data-cerne-otp>
<input class="otp-digit"> <input class="otp-digit"> ...
</div>
<div class="tags-input" data-cerne-tags-input>
<input type="text" placeholder="Adicionar tag...">
</div>
<div class="segmented" role="tablist" data-cerne-segmented>
<button type="button" class="segmented-item is-active" role="tab">30 dias</button>
<!-- ... -->
</div>
<div class="file-drop" data-cerne-file-upload data-cerne-file-list="#file-list">
<input type="file" multiple>
<span>Arraste arquivos aqui ou clique para escolher</span>
</div>
<div class="file-list" id="file-list"></div>
Cards
Mídia
.carousel (um slide por vez, com bolinhas e autoplay opcional) e .shelf (fileira com scroll horizontal, RTL-aware) — para hero de portal institucional e catálogos estilo streaming, respectivamente.
Carrossel (data-cerne-carousel-autoplay)
Prateleira (passe o mouse para revelar as setas)
<div class="carousel" data-cerne-carousel data-cerne-carousel-autoplay="5000">
<div class="carousel-track">
<div class="carousel-slide">...</div>
</div>
<button data-cerne-carousel-prev>‹</button>
<button data-cerne-carousel-next>›</button>
<div class="carousel-dots"></div>
</div>
<div class="shelf" data-cerne-shelf>
<button data-cerne-shelf-prev>‹</button>
<div class="shelf-track">
<div class="shelf-item"><img src="poster.jpg" alt="..." /></div>
</div>
<button data-cerne-shelf-next>›</button>
</div>
Vídeo
Cerne.VideoPlayer — progressive enhancement sobre a marcação de vídeo existente
(não impõe HTML próprio): play/pause, seek por clique, volume, controle de velocidade. Roda em
"relógio simulado" quando não há um <video> real (como abaixo), ou espelha um
<video> nativo (MP4, HLS via hls.js...) quando você passa
[data-video-element] — a entrega real por streaming adaptativo é responsabilidade de
quem implementa, fora do escopo de um framework de CSS/JS.
<div class="player" id="player" data-duration="196">
<button data-video-toggle>▶</button>
<div class="player-controls">
<div class="progress" data-video-seek><div class="progress-bar" data-video-fill></div></div>
<button data-video-mute-toggle>🔊</button>
<input type="range" data-video-volume min="0" max="1" step="0.05" value="1">
<span data-video-time>0:00 / 0:00</span>
<button data-video-speed="1.5">1.5x</button>
</div>
</div>
<script>
new Cerne.VideoPlayer(document.getElementById("player"), { duration: 196 });
</script>
Exemplos completos: vídeo com legendas WebVTT,
streaming com "próximo episódio",
transmissão live: true e
smart TV com navegação por D-pad.
Tabelas & Datatable
.table para tabelas estáticas; [data-cerne-datatable] adiciona ordenação, busca e paginação client-side sem nenhuma dependência.
| Nome | Curso | Progresso |
|---|---|---|
| Marina Silva | Redes de Computadores | 92% |
| Diego Souza | Banco de Dados | 78% |
| Ana Beatriz | Algoritmos | 65% |
| Lucas Pereira | Redes de Computadores | 40% |
| Juliana Melo | Sistemas Operacionais | 88% |
| Rafael Costa | Banco de Dados | 55% |
Conteúdo editorial
Colunas, quadros de destaque, marca-texto com nota explicativa e barra de progresso de leitura — para blog, portal de notícias ou qualquer texto longo dentro de .prose. Aliás, olhe o topo da tela: a barra fina colorida acima do menu é .reading-progress rastreando o scroll desta própria página de documentação.
Quadros (.callout)
<mark> no parágrafo acima — estilo "glossário"/"IA explica" de portais de notícias.
Marca-texto (<mark data-cerne-reveal="mark">) + quadro de glossário — a cor do destaque
"pinta" da esquerda para a direita (ou o inverso em dir="rtl") quando o termo entra na tela,
em vez de aparecer pronto.
O relator destacou que o novo marco regulatório muda o rito de aprovação no plenário.
Colunas de texto (.columns-2 / .columns-3, dentro de .prose)
Primeira coluna: o texto flui verticalmente e quebra para a coluna seguinte.
Segunda coluna: útil para listas curtas de destaques, glossários ou citações — colapsa para 1 coluna abaixo de md.
<p>O novo <mark data-cerne-reveal="mark">marco regulatório</mark> muda o rito de aprovação.</p>
<div class="callout callout-glossary">
<svg class="callout-icon"><use href="sprite.svg#icon-search"></use></svg>
<div class="callout-body"><strong>Marco regulatório</strong> é...</div>
</div>
<div class="columns-2"><p>...</p><p>...</p></div>
<div class="reading-progress"><div class="reading-progress-bar"></div></div>
Veja um exemplo completo em contexto no post do blog ou na matéria do portal de notícias.
Modais & Offcanvas
Confirmar ação
Este é um modal com foco preso (Tab não escapa) e fechamento por Esc, clique fora ou botão.
Painel lateral
Usado para filtros, carrinhos ou detalhes rápidos sem sair da página.
Alertas & Toasts
Calendário & Agendamento
Grade semanal de horários para reserva de salas — veja o exemplo completo em Agendamento.
Gráficos
Mini gráficos SVG sem dependências (Cerne.Chart.bar/line/donut).
Mais componentes
List group, spinner, rating, hero e pricing — para lojas, portais institucionais, páginas de marketing e catálogos.
- Usuários ilimitados
- Suporte prioritário
<div class="rating">
<svg class="is-filled"><use href="sprite.svg#icon-star"></use></svg>
<!-- ... -->
<span class="rating-count">4.2 (128)</span>
</div>
Imagens
Recorte (object-fit/aspect-ratio), filtros CSS
(grayscale, blur-*, brightness-*...) e
receitas de tratamento (zoom no hover, scrim para legenda, duotone, recorte
orgânico) — tudo CSS puro, sem biblioteca de processamento de imagem. As fotos
desta página são ilustrações SVG autorais, para a doc continuar 100%
autocontida.
Recorte & proporção
.aspect-video/.aspect-square/.aspect-portrait
fixam a proporção do contêiner; .object-cover preenche sem distorcer.
<img class="aspect-video object-cover rounded-md" src="foto.jpg" alt="..." />
Filtros
Classes atômicas, combináveis (class="grayscale contrast-125") — cada uma
controla uma única propriedade filter.
<img class="grayscale" src="foto.jpg" alt="..." />
<img class="sepia" src="foto.jpg" alt="..." />
<img class="blur-sm" src="foto.jpg" alt="..." />
<img class="brightness-150 contrast-125" src="foto.jpg" alt="..." />
Tratamentos
Classes de receita (várias propriedades cada, como .bg-aurora) para
padrões comuns de card com foto.
<div class="img-hover-zoom rounded-lg aspect-video">
<img src="foto.jpg" alt="..." />
</div>
<div class="img-scrim rounded-lg aspect-video">
<img src="foto.jpg" alt="..." />
<div class="img-scrim-caption"><strong>Trilha do Vale</strong></div>
</div>
<div class="img-duotone aspect-square"><img src="foto.jpg" alt="..." /></div>
<div class="img-blob aspect-square"><img src="foto.jpg" alt="..." /></div>
Tendências modernas
Bento grid, spotlight card, borda em gradiente, glow, grão/ruído, aurora, marquee, FAB e barra de progresso de leitura — técnicas visuais atuais, prontas para qualquer aplicação.
Marquee (pausa no hover)
data-cerne-reveal — role a página para vê-lo animar.<div class="bento-grid">
<div class="bento-item bento-span-2 card-spotlight">...</div>
<div class="bento-item">...</div>
</div>
<div data-cerne-reveal="up">Aparece ao rolar a página</div>
<span data-cerne-count-up="1284" data-cerne-count-up-format>0</span>
Variantes de utilitário & adaptação regional
hover:, focus:, focus-visible:, active:, disabled:, focus-within: e
dark: na frente de qualquer utilitário de cor/sombra/opacidade, mais group-hover:/peer-checked: em CSS puro
(sem JS — .group/.peer são só marcadores), container queries (.cq + cq-md:) e os primitivos que
tornam o framework adaptável a padrões de UI de qualquer região — não só ocidental.
O botão ao lado usa group-hover:opacity-100 — só aparece quando o pai (.group) está em hover.
data-density="compact" na <html> multiplica toda a escala de espaçamento de uma vez — aproxima o resultado do padrão
de alta densidade de informação comum em portais/e-commerce do Leste Asiático. .break-keep e .write-vertical cobrem
quebra de texto e escrita vertical em CJK; --cerne-line-height-base fica automaticamente mais generoso em
:lang(ar|he|hi|bn|ta|te|th). Veja as 9 páginas de exemplo (loja/notícias/painel × CJK/RTL/Sul da Ásia) em
Ver exemplos.
<div class="group card">
<button class="opacity-25 group-hover:opacity-100 hover:bg-primary">...</button>
</div>
<div class="cq">
<div class="flex-col cq-md:flex-row">...</div> <!-- reage ao espaço do .cq, não do viewport -->
</div>
<html data-density="compact"> <!-- ou "spacious" -->
Ícones
87 ícones em sprite SVG único (dist/icons/sprite.svg), autorais, referenciados via <use>.
Acessibilidade
O alvo é WCAG 2.1 nível AA — o padrão internacional, independente de país ou idioma — não uma ferramenta ou selo específico de uma jurisdição.
- Todo componente interativo tem estado
:focus-visiblevisível e navegação por teclado (setas em tabs/menus, Esc para fechar, Tab preso em modais, roving tabindex em tabs). prefers-reduced-motioneprefers-color-schemesão respeitados automaticamente, sem nenhuma configuração extra.- Cores de texto sobre fundo sólido foram escolhidas para AA — atenção especial em
warning/info, que usam texto escuro em vez de branco por não atingirem contraste suficiente. - Formulários associam rótulo (
for/id), erro earia-invalid; o estado de erro nunca depende só de cor. - Links de navegação ativos recebem
aria-current="page"; landmarks (main,nav,aside) e um<h1>único por página estruturam o documento para leitores de tela. -
Texto alternativo descritivo em imagens/gráficos é responsabilidade de quem usa o framework — o Cerne não consegue gerar isso por você.
A convenção brasileira #PraCegoVer (descrever a imagem no própria legenda/alt) é um bom hábito, mas a prática que importa —
escrever um
altque descreva a imagem, não repita o óbvio — vale em qualquer idioma. - Sobre VLibras e ferramentas de tradução para língua de sinais: propositalmente não vêm embutidas, pois dependem de um script externo (CDN de terceiros) e são específicas de uma língua/país — o que contradiria tanto "zero dependências externas" quanto "framework internacional". A base correta e universal é HTML semântico + ARIA bem feitos, que qualquer tecnologia assistiva do mundo já sabe interpretar; um widget de tradução específico pode ser adicionado por cima, projeto a projeto, quando fizer sentido.
-
RTL de verdade: os componentes usam propriedades lógicas (
inset-inline-start,margin-inline-end,text-align: start...) em vez deleft/rightfixos, então bastadir="rtl"no<html>para espelhar sidebar, dropdown, tabs, formulários e navegação — sem CSS extra. Veja ao vivo:
A borda acompanha o início do texto, não um lado fixo.
<html lang="ar" dir="rtl">
<!-- sidebar, dropdown, tabs, formulários... tudo espelha automaticamente -->
Privacidade & consentimento
Banner de cookies/consentimento genérico — o mesmo padrão de "essencial / análise / marketing" usado por GDPR (UE), LGPD (Brasil) e CCPA (Califórnia), sem depender de nenhuma plataforma de terceiros de gestão de consentimento.
<div class="consent-banner" data-cerne-consent hidden role="region" aria-label="Aviso de cookies">
<p class="consent-banner-text">Usamos cookies essenciais...</p>
<div class="consent-banner-actions">
<button data-cerne-consent-customize
data-cerne-toggle="modal" data-cerne-target="#consent-preferences">Personalizar</button>
<button data-cerne-consent-reject>Rejeitar não essenciais</button>
<button data-cerne-consent-accept>Aceitar tudo</button>
</div>
</div>
<!-- Cerne.Consent.get() / .set({analytics, marketing}) / .reset() -->
A escolha fica em localStorage (chave cerne-consent), nunca em um cookie de terceiros, e nunca é enviada a lugar
nenhum — o que o seu backend faz com Cerne.Consent.get() é decisão sua. O banner só aparece automaticamente quando a página
contém um elemento [data-cerne-consent]; nesta documentação ele foi omitido de propósito para não ser intrusivo — veja o
exemplo completo em Blog, Loja ou
Portal institucional.
Preferências de privacidade
Exemplos completos
42 páginas construídas inteiramente com o Cerne, cobrindo painel administrativo, ensino, gestão, agendamento, conteúdo, portal de notícias, e-commerce, sites institucionais, vídeo, rede social, streaming, assistente conversacional e portfólio — e cada uma delas com uma variante CJK, RTL, Sul da Ásia e Rússia própria, com tradução completa da interface (168 páginas regionais, ~210 no total), acessível pela barrinha "Variante regional" no topo de qualquer exemplo.
Variantes regionais (CJK, RTL, Sul da Ásia, Rússia)
Toda página de todo exemplo acima tem uma variante CJK, RTL, Sul da Ásia e Rússia — 168 páginas regionais no
total — abra qualquer uma e use a barrinha "Variante regional" no topo para navegar entre elas. CJK, RTL e Sul
da Ásia usam os primitivos descritos em Variantes & regional —
data-density, .break-keep/.write-vertical, dir="rtl" e
--cerne-line-height-base por idioma; a variante Rússia usa lang="ru" com texto em
russo sobre a mesma estrutura LTR do exemplo original (sem propriedades lógicas adicionais, já que o russo
se comporta como o português nesse sentido). As 168 páginas têm tradução completa — não só a interface
(navegação, botões, formulários, rótulos, estados vazios), mas também o conteúdo dinâmico: nomes e descrições
de produtos, e-mails de exemplo (assunto e corpo), resultados de busca, títulos e sinopses de vídeo/série, a
conversa de exemplo do assistente e o corpo de artigos e posts longos, cada domínio com sua própria cópia dos
dados de exemplo por idioma (ex. store-data.cjk.browser.js / store-data.ru.browser.js).
O banner de cookies também foi traduzido; só pequenas notas de rodapé descrevendo a própria variante (e nomes
próprios de pessoas) permanecem em português, por serem texto de documentação para quem está lendo o
código-fonte, não conteúdo do app.
| Exemplo | CJK | RTL | Sul da Ásia | Rússia |
|---|---|---|---|---|
| Painel administrativo | Abrir | Abrir | Abrir | Abrir |
| Ambiente de aprendizagem | Abrir | Abrir | Abrir | Abrir |
| Página de professor | Abrir | Abrir | Abrir | Abrir |
| Gestão / CRUD | Abrir | Abrir | Abrir | Abrir |
| Agendamento de salas | Abrir | Abrir | Abrir | Abrir |
| Blog | Abrir | Abrir | Abrir | Abrir |
| Blog — post | Abrir | Abrir | Abrir | Abrir |
| Portal de notícias | Abrir | Abrir | Abrir | Abrir |
| Portal de notícias — artigo | Abrir | Abrir | Abrir | Abrir |
| Loja e-commerce | Abrir | Abrir | Abrir | Abrir |
| Loja e-commerce — produto | Abrir | Abrir | Abrir | Abrir |
| Site de laboratório | Abrir | Abrir | Abrir | Abrir |
| Portal institucional | Abrir | Abrir | Abrir | Abrir |
| Site de grupo de pesquisa | Abrir | Abrir | Abrir | Abrir |
| Autenticação — login | Abrir | Abrir | Abrir | Abrir |
| Autenticação — cadastro | Abrir | Abrir | Abrir | Abrir |
| Autenticação — verificação OTP | Abrir | Abrir | Abrir | Abrir |
| Erro 404 | Abrir | Abrir | Abrir | Abrir |
| Erro 500 | Abrir | Abrir | Abrir | Abrir |
| Plataforma de vídeos | Abrir | Abrir | Abrir | Abrir |
| Vídeos — assistir | Abrir | Abrir | Abrir | Abrir |
| Vídeos — playlist | Abrir | Abrir | Abrir | Abrir |
| Rede social (feed) | Abrir | Abrir | Abrir | Abrir |
| Rede social (perfil) | Abrir | Abrir | Abrir | Abrir |
| Streaming — login | Abrir | Abrir | Abrir | Abrir |
| Streaming — perfis | Abrir | Abrir | Abrir | Abrir |
| Streaming de vídeo | Abrir | Abrir | Abrir | Abrir |
| Streaming — título | Abrir | Abrir | Abrir | Abrir |
| Streaming — assistir | Abrir | Abrir | Abrir | Abrir |
| Streaming — explorar | Abrir | Abrir | Abrir | Abrir |
| Streaming — ao vivo | Abrir | Abrir | Abrir | Abrir |
| Assistente conversacional (LLM) | Abrir | Abrir | Abrir | Abrir |
| Portfólio (grade bento) | Abrir | Abrir | Abrir | Abrir |
| Painel de analytics | Abrir | Abrir | Abrir | Abrir |
| Webmail (estilo Gmail) | Abrir | Abrir | Abrir | Abrir |
| Webmail (estilo Outlook) | Abrir | Abrir | Abrir | Abrir |
| Buscador (minimalista) | Abrir | Abrir | Abrir | Abrir |
| Buscador (minimalista) — resultados | Abrir | Abrir | Abrir | Abrir |
| Buscador (portal denso) | Abrir | Abrir | Abrir | Abrir |
| Buscador (portal denso) — resultados | Abrir | Abrir | Abrir | Abrir |
| Interface de smart TV | Abrir | Abrir | Abrir | Abrir |
| Smart TV — player | Abrir | Abrir | Abrir | Abrir |
| Cadastro internacional adaptativo (já adapta por país via JS — sem variantes estáticas) | — | — | — | — |